java web项目防止多用户重复登录解决方案

13 篇文章 0 订阅

目前web项目中,很多情况都是可以让同一个账户信息在不同的登录入口登录这次,这样子就不那么美好了。

现在有两种解决方案:

1、将用户的登录信息用一个标志位的字段保存起来,每次登录成功就标记1,注销登录就标记为0,当标记为1的时候不允许别人登录。

2、将用户的登录信息保存在application内置作用域内, 然后利用session监听器监听每一个登录用户的登录情况。

很显然,第一种方式 每次登录 都需要操作数据库,多了一些不必要的性能开销,而且在登录状态下 万一突然电脑关闭了,那就永远都不能登录了,可用性比较低。

但是第二种方式就不一样了,可操作性强,很方便维护所有在线用户的信息。

接下来 主要介绍第二种方式的具体实现:

1、在处理登录的login方法中,先查询数据库验证下该用户是否存在,如果存在 判断该登录账户是否已经锁定了, 然后从application内置作用域对象中取出所有的登录信息,查看该username账户是否已经登录,如果登录了,就友好提示下,反之表示可以登录,将该登录信息保存在application中。

代码如下:

[java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//没有使用零配置前 每个访问的方法都要加上@Action ,否则404  
@Action (value= "login" , results={ 
         @Result (name= "index" , location= "index.jsp" ), 
}) 
public  String login()  throws  Exception { 
     try
         User result = userService.login(user.getFuUserName(), user.getFuPassword()); 
         if (result!= null ){ 
             if (result.getFuStatus()!= null  && result.getFuStatus()== 0 ){ 
                 super .setRequestAttr(Constant.MESSAGE,  "抱歉,该用户已被锁定!" ); 
                 return  "error"
            
             Map<String, String> loginUserMap = (Map<String, String>) super .getApplicationAttr(Constant.LOGIN_USER_MAP); 
             boolean  isExist =  false
             String sessionId =  super .getSessionId( false ); 
             if (loginUserMap== null ){ 
                 loginUserMap =  new  HashMap<String, String>(); 
            
             for  (String username : loginUserMap.keySet()) { 
                 //判断是否已经保存该登录用户的信息         并且     如果是同一个用户进行重复登录那么允许登录  
                 if (!username.equals(result.getFuUserName()) || loginUserMap.containsValue(sessionId)){ 
                     continue
                
                 isExist =  true
                 break
             }                
             if (isExist){ 
                 super .setRequestAttr(Constant.MESSAGE,  "抱歉,该用户已登录!" ); 
                 return  "error"
             } else 
                 loginUserMap.put(result.getFuUserName(), sessionId); 
            
             //登录成功  
             super .setSessionAttr(Constant.LOGIN_USER, result); 
             super .setApplicationAttr(Constant.LOGIN_USER_MAP, loginUserMap); 
                
             logger.info(result.getFuUserName() +  " 登录成功!" ); 
             //如果 session中fromUrl有值,就跳转到该页面  
             String fromUrl = (String) super .getSessionAttr(Constant.FROM_URL); 
             if (fromUrl!= null ){ 
                 super .setSessionAttr(Constant.FROM_URL,  null ); 
                 super .getResponse().sendRedirect(fromUrl.toString()); 
                 return  null
            
             return  "index"
        
    
     catch  (Exception e) { 
         e.printStackTrace(); 
         logger.info( "登录失败: " +e.getMessage()); 
    
     super .setRequestAttr( "message" "用户名或密码错误" ); 
     return  "error"
//没有使用零配置前 每个访问的方法都要加上@Action ,否则404
@Action (value= "login" , results={
@Result (name= "index" , location= "index.jsp" ),
})
public  String login()  throws  Exception {
try {
User result = userService.login(user.getFuUserName(), user.getFuPassword());
if (result!= null ){
if (result.getFuStatus()!= null  && result.getFuStatus()== 0 ){
super .setRequestAttr(Constant.MESSAGE,  "抱歉,该用户已被锁定!" );
return  "error" ;
}
Map<String, String> loginUserMap = (Map<String, String>) super .getApplicationAttr(Constant.LOGIN_USER_MAP);
boolean  isExist =  false ;
String sessionId =  super .getSessionId( false );
if (loginUserMap== null ){
loginUserMap =  new  HashMap<String, String>();
}
for  (String username : loginUserMap.keySet()) {
//判断是否已经保存该登录用户的信息         并且     如果是同一个用户进行重复登录那么允许登录
if (!username.equals(result.getFuUserName()) || loginUserMap.containsValue(sessionId)){
continue ;
}
isExist =  true ;
break ;
}
if (isExist){
super .setRequestAttr(Constant.MESSAGE,  "抱歉,该用户已登录!" );
return  "error" ;
} else  {
loginUserMap.put(result.getFuUserName(), sessionId);
}
//登录成功
super .setSessionAttr(Constant.LOGIN_USER, result);
super .setApplicationAttr(Constant.LOGIN_USER_MAP, loginUserMap);
logger.info(result.getFuUserName() +  " 登录成功!" );
//如果 session中fromUrl有值,就跳转到该页面
String fromUrl = (String) super .getSessionAttr(Constant.FROM_URL);
if (fromUrl!= null ){
super .setSessionAttr(Constant.FROM_URL,  null );
super .getResponse().sendRedirect(fromUrl.toString());
return  null ;
}
return  "index" ;
}
}
catch  (Exception e) {
e.printStackTrace();
logger.info( "登录失败: " +e.getMessage());
}
super .setRequestAttr( "message" "用户名或密码错误" );
return  "error" ;
}

2、登录入口处理完之后,考虑到回话结束的话,那么对应的登录用户也应该相应的注销登录。我们可以写一个Session监听器,监听sessioon销毁的时候,我们将登录的用户注销掉,也就是从application中移除。表示该用户已经下线了。

代码如下:

[java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
public  class  SessionListener  implements  HttpSessionListener,ServletContextListener{ 
    
     private  int  count; 
     private  ServletContext servletContext =  null
        
     public  SessionListener() { 
         count =  0
    
    
     private  Logger logger = Logger.getLogger( this .getClass()); 
     @Override
     public  void  sessionCreated(HttpSessionEvent event) { 
         count++; 
         setContext(event); 
         logger.info( "***************the  http session is created...***************" ); 
    
    
     @Override
     public  void  sessionDestroyed(HttpSessionEvent event) { 
         //在session销毁的时候 把loginUserMap中保存的键值对清除  
         User user = (User)event.getSession().getAttribute( "loginUser" ); 
         if (user!= null ){ 
             Map<String, String> loginUserMap = (Map<String, String>)event.getSession().getServletContext().getAttribute( "loginUserMap" ); 
             loginUserMap.remove(user.getFuUserName()); 
             event.getSession().getServletContext().setAttribute( "loginUserMap" ,loginUserMap); 
        
            
         count--; 
         setContext(event); 
         logger.info( "***************the  http session is destroyed...***************" ); 
    
    
     public  void  setContext(HttpSessionEvent httpSessionEvent){ 
         httpSessionEvent.getSession().getServletContext().setAttribute( "online" , count); 
    
        
        
     @Override
     public  void  contextDestroyed(ServletContextEvent servletcontextevent) {      
         this .servletContext =  null
         logger.info( "***************the  servlet context is destroyed...***************" ); 
    
    
     @Override
     public  void  contextInitialized(ServletContextEvent servletcontextevent) { 
         this .servletContext = servletcontextevent.getServletContext(); 
         logger.info( "***************the  servlet context is initialized...***************" ); 
    
public  class  SessionListener  implements  HttpSessionListener,ServletContextListener{
private  int  count;
private  ServletContext servletContext =  null ;
public  SessionListener() {
count =  0 ;
}
private  Logger logger = Logger.getLogger( this .getClass());
@Override
public  void  sessionCreated(HttpSessionEvent event) {
count++;
setContext(event);
logger.info( "***************the  http session is created...***************" );
}
@Override
public  void  sessionDestroyed(HttpSessionEvent event) {
//在session销毁的时候 把loginUserMap中保存的键值对清除
User user = (User)event.getSession().getAttribute( "loginUser" );
if (user!= null ){
Map<String, String> loginUserMap = (Map<String, String>)event.getSession().getServletContext().getAttribute( "loginUserMap" );
loginUserMap.remove(user.getFuUserName());
event.getSession().getServletContext().setAttribute( "loginUserMap" ,loginUserMap);
}
count--;
setContext(event);
logger.info( "***************the  http session is destroyed...***************" );
}
public  void  setContext(HttpSessionEvent httpSessionEvent){
httpSessionEvent.getSession().getServletContext().setAttribute( "online" , count);
}
@Override
public  void  contextDestroyed(ServletContextEvent servletcontextevent) {
this .servletContext =  null ;
logger.info( "***************the  servlet context is destroyed...***************" );
}
@Override
public  void  contextInitialized(ServletContextEvent servletcontextevent) {
this .servletContext = servletcontextevent.getServletContext();
logger.info( "***************the  servlet context is initialized...***************" );
}
web.xml中配置如下:
[html] view plaincopyprint?
<!-- session listener --> 
<listener> 
     <listener- class >com.facelook.util.SessionListener</listener- class
</listener> 
<!-- session listener -->
<listener>
<listener- class >com.facelook.util.SessionListener</listener- class >
</listener>

3、另外,还有一个问题,如果说登录的用户突然关闭了浏览器而没有点击退出按钮。那么可以利用beforeunload 事件,在浏览器刷新或者关闭的时候触发。

[java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//在刷新或关闭时调用的事件  
$(window). bind ( 'beforeunload' , function (){ 
   $.ajax({ 
     url: "${ctx}/system/user/user!logout.action"
     type: "post"
     success: function (){ 
         alert( "您已退出登录" ); 
    
}); 
); 
   //在刷新或关闭时调用的事件
   $(window). bind ( 'beforeunload' , function (){
    $.ajax({
url: "${ctx}/system/user/user!logout.action" ,
type: "post" ,
success: function (){
alert( "您已退出登录" );
}
});
});

这样子,基本上可以实现防止多用户登录的案例了!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值