ajax 调用无法识别 Spring Security 会话超时
Posted
技术标签:
【中文标题】ajax 调用无法识别 Spring Security 会话超时【英文标题】:Spring Security sesson timeout not recognized on ajax call 【发布时间】:2011-10-18 19:54:44 【问题描述】:我想在会话超时时将用户重定向到登录页面。这适用于 Spring Security 开箱即用,但仅适用于非 ajax 调用。
在 ajax 调用中,您必须自己对会话超时做出反应。因此我创造了
我自己的过滤器(过滤器在this question 中实现)检查会话是否超时。过滤器是通过 spring 安全配置中的custom-filter
标签注册的。
<http use-expressions="true">
<custom-filter ref="customTimeoutHandler" after="LAST"/>
</http>
问题是,过滤器无法识别会话超时。如果我检查request.isRequestedSessionIdValid()
,即使会话超时,它也会返回true
。当我手动输入新的安全 URL 时,标准 spring 安全过滤器会正确识别超时并重定向到登录页面。
这里可能有什么问题? spring security 如何识别会话超时?
更新
看来,spring security 的会话管理过滤器用一个新的匿名会话替换了超时会话。因此,每次我检查会话超时时,它都会返回 true
,因为新的匿名会话当然不会超时。
【问题讨论】:
【参考方案1】:您可以查看SecurityContext
。
抓住Authentication
object 和check the authorities 寻找ANONYMOUS
一个。比如:
SecurityContext sc = SecurityContextHolder.getContext();
Authentication a = sc.getAuthentication();
if(!a.isAuthenticated() || a.getAuthorities().contains(new GrantedAuthorityImpl("ROLE_ANONYMOUS")))
//user not authenticated or ANONYMOUS
else
//user authenticated
【讨论】:
【参考方案2】:This solution 对我来说就像一个魅力。
基本概念是指向一个 servlet 而不是登录页面。然后,servlet 确定该请求是否为 ajax 请求,如果为真,则将重定向作为 xml 片段返回到登录页面。浏览器可以解释该片段并重定向到登录页面。
【讨论】:
【参考方案3】:我正在开发企业应用程序,包括 gwt/gwtp 和 spring security 。 我添加了一些会话超时问题,因为默认使用的 SimpleRedirectInvalidSessionStrategy 正在执行 response.sendRedirect() ,我想要重定向的 html 页面响应被 gwt com.google.gwt.user.client.rpc.InvocationException 吞下为异常消息。并且实际上没有发生重定向。
解决这个问题
1 .我定义了我的 cosutom session-manamgemt-filter
为此,您需要在 spring-security.xml 配置文件集中
<session-management session-fixation-protection="none"/>
今年春季安全不会采用默认会话管理过滤器。
定义您的会话管理过滤器
在此处输入代码
<custom-filter position="SESSION_MANAGEMENT_FILTER" ref="mySessionManagmentFilter"/>
<beans:bean id="mySessionManagmentFilter"
class="org.springframework.security.web.session.SessionManagementFilter">
<beans:constructor-arg index="0" ref="mySessionSecurityContextRepository"/>
<beans:constructor-arg index="1" ref="mySessionAutenticationStrategy"/>
<beans:property name="invalidSessionStrategy">
<beans:ref local="myInvalidSessionStrategy"/>
</beans:property>
</beans:bean>
<beans:bean id="mySessionSecurityContextRepository"
class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
<beans:property name='allowSessionCreation' value='false'/>
</beans:bean>
<beans:bean id="mySessionAutenticationStrategy"
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry"/>
<beans:property name="maximumSessions" value="1"/>
<beans:property name="exceptionIfMaximumExceeded" value="false"/>
<beans:property name="alwaysCreateSession" value="true"/>
</beans:bean>
<beans:bean id="myInvalidSessionStrategy"
class="com.my.project.MyInvalidSessionStrategy">
<beans:constructor-arg value="/login.jsp?timeout=1"/>
</beans:bean>
这里自定义 - MyInvalidSessionStrategy
public class MyInvalidSessionStrategy implements InvalidSessionStrategy
private final Logger logger = LoggerFactory.getLogger(getClass());
private final String destinationUrl;
public OperationalInvalidSessionStrategy(String invalidSessionUrl)
this.destinationUrl = invalidSessionUrl;
@Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
String exMsg =session timeout ! , need to redirect to login page
logger.warn(exMsg);
throw new TimeOutException(exMsg);
所以当超时发生时,新的实现会抛出异常.. 异常可以是卡车上 gwt 回调 onFailure 方法
检查异常的类型并在 onFailure 方法上将用户重定向到登录页面。
Window.Location.replace(GWT.getHostPageBaseURL() + "/login.jsp")
【讨论】:
以上是关于ajax 调用无法识别 Spring Security 会话超时的主要内容,如果未能解决你的问题,请参考以下文章
jQuery 似乎无法识别具有 Ajax 调用状态码 403 的不同字符串
无法从简单的 Ajax 函数调用 Spring Boot RestController 中的 GET 方法