用到的技術: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#