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類,但是並沒有添加這兩個方法,也可以正常實現效果。

發佈了16 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章