注销时如何使用户会话无效?
Posted
技术标签:
【中文标题】注销时如何使用户会话无效?【英文标题】:How Invalidate users sessions when makes logout? 【发布时间】:2012-01-24 16:24:51 【问题描述】:我花了很多时间来解决这个问题,但仍然无法解决。
我正在使用 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>
【问题讨论】:
【参考方案1】:以下是适用于多服务器方案的 3 个解决方案:
在负载平衡器上使用粘性会话,以便用户不断返回到同一台服务器。然后,您只需在他们注销时使会话无效。这通常与会话故障转移解决方案 (Tomcat example) 结合使用,因此如果服务器出现故障,用户可以被重定向到接收旧会话的新服务器。
为会话使用分布式缓存(例如Terracotta Web Sessions)。然后当他们注销时使会话失效,并且它将在任何地方失效。
另一个解决方案是使用自定义的 Spring Security TokenBasedRememberMeServices 作为您的“登录”cookie。如果用户没有选择记住我,请继续设置 cookie,但将其设置为浏览器会话 cookie 而不是持久性 cookie。所有服务器都将识别用户并为其创建会话。当用户注销时,删除 cookie。您还需要一个自定义的 RememberMeAuthenticationFilter 来查找会话中的身份验证令牌和丢失的 RememberMe cookie,如果是这种情况,则使会话无效并清除安全上下文。
【讨论】:
【参考方案2】:我建议您查看 SessionRegistry 。您可以查看此 here 。 Is it possible to invalidate a spring security session? 对此进行了讨论。也看看这个
Spring 会话存储为 JsessionID cookie。查看here 了解有关删除 cookie 的讨论。
Invalid a session when user makes logout (Spring) 讨论了相同的查询。
【讨论】:
其实这整个答案都是单服务器的答案。以上是关于注销时如何使用户会话无效?的主要内容,如果未能解决你的问题,请参考以下文章
使Java HTTP会话无效以重定向到其他服务器,而无需将用户注销