注销时如何使用户会话无效?

时间:2011-12-20 18:11:49

标签: spring authentication cookies spring-security sessionid

我花了很多时间来解决这个问题,但仍然无法让它发挥作用。

我正在使用Spring Security。该应用程序将在多个服务器上运行。我在登录时使用“记住我”选项来保存我的数据库中的持久登录。

如果用户连接到服务器1,则他在Cookie浏览器中具有会话ID。我打开另一台服务器,此用户进行身份验证,cookie浏览器具有此会话ID和服务器1连接的会话ID。

当此用户在一台服务器或另一台服务器中注销时,应将其重定向到所有服务器的登录页面。

我尝试从浏览器中删除Cookie但没有成功。我怎样才能做到这一点?有什么帮助吗?

示例方案:在Gmail中,如果您的帐户中有2个选项卡已打开,并且您从其中一个选项卡中注销,则其他选项卡也会自动注销。服务器1不知道服务器2的信息。我认为我的问题在这里,但我不知道如何解决这个问题。

这是我的安全配置:

<http auto-config="false" use-expressions="true" disable-url-rewriting="true">
   <intercept-url pattern="/login.do" access="permitAll" />
   <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
   <remember-me data-source-ref="dataSource" />
   <form-login login-page="/login.do" />
   <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
   <custom-filter position="LOGOUT_FILTER" ref="logoutFilter" />
   <session-management session-authentication-strategy-ref="sas" />
</http>

<!-- <logout logout-url="/j_spring_security_logout" logout-success-url="/" invalidate-session="true" /> -->

<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
   <beans:constructor-arg value="/login.do" />
   <beans:constructor-arg>
      <beans:list>
         <beans:ref bean="rememberMeServices"/>
         <beans:ref bean="logoutHandler"/>
      </beans:list>
   </beans:constructor-arg>
   <!-- <beans:property name="filterProcessesUrl" value="/login.do" /> -->
</beans:bean>

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

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

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

<authentication-manager alias="authenticationManager">
   <authentication-provider user-service-ref="jdbcUserService" />
</authentication-manager>

2 个答案:

答案 0 :(得分:5)

以下是针对多服务器方案的3种解决方案:

  1. 在负载均衡器上使用粘性会话,以便用户继续返回同一服务器。然后,您只需在会话注销时使会话无效。这通常与会话故障转移解决方案(Tomcat example)结合使用,因此如果服务器出现故障,用户可以重定向到新服务器以获取旧会话。

  2. 为会话使用分布式缓存(例如Terracotta Web Sessions)。然后当他们注销时会使会话无效,并且它将在所有地方失效。

  3. 另一种解决方案是使用自定义的Spring Security TokenBasedRememberMeServices作为“登录”cookie。如果用户没有选择记住我,请继续设置cookie,但将其设为浏览器会话cookie而不是持久性cookie。所有服务器都将识别用户并为其创建会话。当用户注销时,请删除cookie。您还需要一个自定义的RememberMeAuthenticationFilter,它在会话中查找身份验证令牌和一个缺少的RememberMe cookie,如果是这种情况,会话无效并清除安全上下文。

答案 1 :(得分:1)

我建议您查看SessionRegistry。您可以查看here。在Is it possible to invalidate a spring security session?进行了讨论。检查一下

Spring会话存储为JsessionID cookie。请查看here以了解有关删除Cookie的讨论。

Invalid a session when user makes logout (Spring)已讨论过相同的查询。