Spring Security控制只能有一个用户在线

在最近的一个项目中需要用到同时只能允许一个用户在线,该系统是一个线上考试系统,要求同一个考生在不同的浏览器上同时只能有一个在线。框架用的Spring Security,Spring Security本身时有关于Session控制的,只需要在配置文件中进行配置就可以实现。

第一步需要在web.xml里配置HttpSessionEventPublisher,如下所示,只要在web.xml文件里加上这段配置就可以


        org.springframework.security.web.session.HttpSessionEventPublisher
 

第二部需要配置Spring Security的配置文件,我这里的文件名字是security.xml,这个名字可能会不一样,这要看各自的具体命名。

如果只是简单的应用Spring Security,只需要在配置文件中加上下面这段配置就可以了

            invalid-session-url="/user-login-page"
            session-authentication-error-url="/user-login-page">
                             max-sessions="1" expired-url="/home" error-if-maximum-exceeded="false" />
        

其中invalid-session-url是配置会话失效转向地址;max-sessions是设置单个用户最大并行会话数;error-if-maximum-exceeded是配置当用户登录数达到最大时是否报错,设置为true时会报错且后登录的会话不能登录,默认为false不报错且将前一会话置为失效。
配置完后使用不同浏览器登录系统,就可以看到同一用户后来的会话不能登录或将已登录会话踢掉。

 

但是如果spring security的一段中使用了自定义过滤器(特别是FORM_LOGIN_FILTER),或者配置了AuthenticationEntryPoint,或者使用了自定义的UserDetails、AccessDecisionManager、AbstractSecurityInterceptor、FilterInvocationSecurityMetadataSource、UsernamePasswordAuthenticationFilter等,上面的简单配置可能就不会生效了,就需要自行配置ConcurrentSessionFilter、ConcurrentSessionControlStrategy和SessionRegistry,虽然配置内容和缺省一致。配置如下:

        class="org.springframework.security.web.session.ConcurrentSessionFilter">  
          
          
    

             class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">  
                     ref="sessionRegistry" />  
          
    

             class="org.springframework.security.core.session.SessionRegistryImpl">
    

此外还需要在

这个地方之所以用after="CONCURRENT_SESSION_FILTER",是因为我的配置文件里已经有了一个custom-filter,为了区分先后顺序,所以把原来的custom-filter改为before="FORM_LOGIN_FILTER" ref="securityFilter" />。

基本上经过上述步骤以后启动项目,分别打开浏览器然后进行的登录就可以看到效果了。

网上有的文章还说如果自己有自定义的UserDetail的话还需要在自己的类里面加上

@Override  
public boolean equals(Object rhs) {  
    if (rhs instanceof User) {  
        return username.equals(((User) rhs).username);  
    }  
    return false;  
}  
  
/** 
 * Returns the hashcode of the {@code username}. 
 */  
@Override  
public int hashCode() {  
    return username.hashCode();  
}  

这两个方法,虽然我这里也自定义了UserDetail类,但是并没有添加这两个方法,也可以正常实现效果。

你可能感兴趣的:(SpringSecurity)