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

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

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

<listener>
        <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
 </listener>

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

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

<security:session-management
            invalid-session-url="/user-login-page"
            session-authentication-error-url="/user-login-page">
            <security:concurrency-control
                max-sessions="1" expired-url="/home" error-if-maximum-exceeded="false" />
        </security:session-management>

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

 

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

<bean id="concurrencyFilter"  
        class="org.springframework.security.web.session.ConcurrentSessionFilter">  
        <property name="sessionRegistry" ref="sessionRegistry" />  
        <property name="expiredUrl" value="/user-login-page?result=failed" />  
    </bean>
    <bean id="sessionAuthenticationStrategy"  
        class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">  
        <constructor-arg name="sessionRegistry"  
            ref="sessionRegistry" />  
        <property name="maximumSessions" value="1" />  
    </bean>
    <bean id="sessionRegistry"  
        class="org.springframework.security.core.session.SessionRegistryImpl">
    </bean>

此外还需要在<security:http中加上下面的配置

<security:custom-filter after="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />

这个地方之所以用after="CONCURRENT_SESSION_FILTER",是因为我的配置文件里已经有了一个custom-filter,为了区分先后顺序,所以把原来的custom-filter改为<security: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类,但是并没有添加这两个方法,也可以正常实现效果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值