2010-09-08 58 views
4

我試圖限制用戶不止一次簽名(迫使以前的會話過期)。Spring Security,表單登錄和併發會話

我已經檢查了有關主題here的文檔。我已經把它設置得非常類似於文檔,但用戶並沒有被限制在一個會話中。我可以使用同一個用戶多次(在不同的瀏覽器中)登錄,並且有多個併發會話正在進行。

下面是我認爲是我的安全設置的相關位。我使用自定義的UserDetailsS​​ervice,UserDetails和AuthenticationFilter實現。


    <http entry-point-ref="authenticationEntryPoint"> 
     <!-- Make sure everyone can access the login page --> 
     <intercept-url pattern="/login.do*" filters="none" /> 

     [...] 

     <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" /> 
     <custom-filter position="FORM_LOGIN_FILTER" ref="authenticationFilter" /> 

     <logout logout-url="/logout" logout-success-url="/login.do" /> 
    </http> 

    <authentication-manager alias="authenticationManager"> 
     <authentication-provider user-service-ref="userDetailsService"> 
      <password-encoder hash="sha" /> 
     </authentication-provider> 
    </authentication-manager> 

    <beans:bean id="userDetailsService" class="[...]"> 
     <beans:property name="userManager" ref="userManager" /> 
    </beans:bean> 

    <beans:bean id="authenticationFilter" class="[...]"> 
     <beans:property name="authenticationManager" ref="authenticationManager" /> 
     <beans:property name="eventPublisher"> 
      <beans:bean 
       class="org.springframework.security.authentication.DefaultAuthenticationEventPublisher" /> 
     </beans:property> 
     <beans:property name="filterProcessesUrl" value="/security_check" /> 
     <beans:property name="authenticationFailureHandler"> 
      <beans:bean 
       class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> 
       <beans:property name="defaultFailureUrl" value="/login.do?login_error=true" /> 
      </beans:bean> 
     </beans:property> 
     <beans:property name="sessionAuthenticationStrategy" 
      ref="sessionAuthenticationStrategy" /> 
    </beans:bean> 

    <beans:bean id="authenticationEntryPoint" 
     class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> 
     <beans:property name="loginFormUrl" value="/login.do" /> 
    </beans:bean> 

    <beans:bean id="concurrencyFilter" 
     class="org.springframework.security.web.session.ConcurrentSessionFilter"> 
     <beans:property name="sessionRegistry" ref="sessionRegistry" /> 
     <beans:property name="expiredUrl" value="/login.do?login_error=true!" /> 
    </beans:bean> 

    <beans:bean id="sessionAuthenticationStrategy" 
     class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"> 
     <beans:constructor-arg name="sessionRegistry" 
      ref="sessionRegistry" /> 
     <beans:property name="maximumSessions" value="1" /> 
    </beans:bean> 

    <beans:bean id="sessionRegistry" 
     class="org.springframework.security.core.session.SessionRegistryImpl" /> 

我也註冊org.springframework.security.web.session.HttpSessionEventPublisher在我的web.xml文件中的監聽器。

據我所知,我已經根據文檔配置了它。我不明白爲什麼這不起作用。這可能與我使用基於表單的登錄有關嗎?或者我上面提到的自定義實現?

回答

9

我想通了。如果您重新實現UserDetails,則必須爲SessionRegistryImpl提供一個使用的hashCode()方法。這在文檔中沒有提及。

+0

感謝您的回答,我有類似的問題,但在閱讀本文後,我在['User'](http://static.springsource.org/spring)中發現了關於'hashCode()'和'equals() -security/site/docs/3.0.x/apidocs/org/springframework/security/core/userdetails/User.html)類的註釋,這暗示了在你的類中重寫這兩個方法。 – Xaerxess 2011-11-30 09:05:52

+0

我一直在尋找這個答案,所以很多時間:)它的作品! – sanluck 2016-04-14 02:19:29

2

我知道這已被回答,但有一個更簡單的解決方案,不需要配置特定的過濾器。您可以添加到HTTP標籤下面的XML配置您的會話:

<session-management invalid-session-url="/login"> 
    <concurrency-control max-sessions="1" expired-url="/login" /> 
</session-management> 

基於表單登錄配置的其餘部分也過於複雜。我在這裏寫了一篇文章http://codehustler.org/blog/spring-security-form-login-tutorial/,其中顯示瞭如何正確配置表單登錄。