用到的技术:map集合,sessionListener监听器,Fiter过滤器。
实现思路:
一.利用一个全局的map集合来保存每个用户sessionID的值的一个集合。一个用户对应一个sessionID当相同的用户登录的时候判断它在集合总有没有值。(保存用户所有登录记录)
二.
2.1.实现sessionListener在当一个session被销毁的时候强制移除当前用户所对应的sessionID
2.2.实现Fiter来判断每次请求map集合中是否有值。(实现强制退出)
代码:代码是复制别人的,做了些修改。
public
class
LoginUserMap {
//
ConcurrentHashMap这个集合是线程安全的而且性能方面比hasTable和hasMap都好。在高并发的条件下执行速度更快。
private
static
Map<String, String> loginUsers =
new
ConcurrentHashMap<String, String>();
/**
* 将用户和sessionId存入map
* @param key
* @param value
*/
public
static
void
setLoginUsers(String loginId, String sessionId) {
loginUsers.put(loginId, sessionId);
}
/**
* 获取loginUsers
* @return
*/
public
static
Map<String, String> getLoginUsers() {
return
loginUsers;
}
/**
* 根据sessionId移除map中的值
* @param sessionId
*/
public
static
void
removeUser(String sessionId) {
for
(Map.Entry<String, String> entry : loginUsers.entrySet()) {
if
(sessionId.equals(entry.getValue())) {
loginUsers.remove(entry.getKey());
break
;
}
}
}
/**
* 判断用户是否在loginusers中
* @param loginId
* @param sessionId
* @return
*/
public
static
boolean
isInLoginUsers(String loginId, String sessionId) {
return
(loginUsers.containsKey(loginId) && sessionId.equals(loginUsers.get(loginId)));
}
}
//登录方法所在的地方
public
void
login(ttpServletRequest request) {
try
{
......
//一系列登录的方法
HttpSession session = request.getSession();
LoginUserMap.setLoginUsers(username, session.getId());
//保存sessionId到map中
}
catch
(LoginException ex) {
throw
ex;
}
}
//实现
HttpSessionListener
public
class
SessionListener
implements
HttpSessionListener {
private
Log log = LogFactory.getLog(SessionListener.
class
);
/**
* 创建session时候的动作
* @param event
*/
@Override
public
void
sessionCreated(HttpSessionEvent event) {
}
/**
* 销毁session时候的动作
* @param event
*/
@Override
public
void
sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
String sessionId = session.getId();
//移除loginUsers中已经被销毁的session
LoginUserMap.removeUser(sessionId);
log.info(sessionId +
"被销毁!"
);
}
}
//xml配置
<
listener
>
<
listener-class
>....SessionListener</
listener-class
>
</
listener
>
//实现过滤器
public
class
LoginLimitFilter
implements
Filter{
private
Log log = LogFactory.getLog(LoginLimitFilter.
class
);
/**
* 销毁时的方法
*/
@Override
public
void
destroy() {
}
/**
* 过滤请求
* @param request
* @param response
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public
void
doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain)
throws
IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
HttpSession session = servletRequest.getSession();
//获取项目路径
String path = servletRequest.getContextPath();
String basePath = servletRequest.getScheme()+
"://"
+servletRequest.getServerName()+
":"
+servletRequest.getServerPort()+path;
try
{
//获取登录信息
String loginId = session.getAttribute("yhid")
//判断当前用户的sessionId是否在loginUsers中,如果没有执行if后的操作
if
(!LoginUserMap.isInLoginUsers(loginId, session.getId())) {
//当前用户logout 注:退出登录最好别用session销毁的方法。
logout();
//自己的logout方法
//调到登录页面,并表明退出方式为挤下线
servletResponse.sendRedirect(basePath +
"?logoutway=edge"
);
}
}
catch
(Exception e) {
log.debug(
"获取当前用户信息失败,用户未登陆!"
, e);
}
finally
{
filterChain.doFilter(request, response);
}
}
/**
* 初始化方法
* @param arg0
* @throws ServletException
*/
@Override
public
void
init(FilterConfig arg0)
throws
ServletException {
}
}
//xml
<
filter
>
<
filter-name
>LoginLimitFilter</
filter-name
>
<
filter-class
>io.github.brightloong.loginlimite.LoginLimitFilter</
filter-class
>
</
filter
>
<
filter-mapping
>
<
filter-name
>LoginLimitFilter</
filter-name
>
<
url-pattern
>/*</
url-pattern
>
</
filter-mapping
>
//前台页面js放在首页就可以了
window.onload = function(){
if
(window.parent != window){
window.parent.location.href=window.location.href;
}
else
{
if
(GetQueryString(
'logoutway'
)) {
alert('该用户已在其他地方登录,你已下线');
var url = window.location.href;
window.location.href = url.substr(
0
,url.indexOf(
'?logoutway=edge'
));
}
}
}
function GetQueryString(name)
{
var reg =
new
RegExp(
"(^|&)"
+ name +
"=([^&]*)(&|$)"
);
var r = window.location.search.substr(
1
).match(reg);
if
(r!=
null
)
return
unescape(r[
2
]);
return
null
;
}
原文链接:http://www.jianshu.com/p/24bc2bb1444e#