我看不到有关如何在会话超时时从ajax请求发回一些数据的好示例/答案。它发回登录页面HTML,我想发送json或我可以拦截的状态代码。
答案 0 :(得分:11)
执行此操作的最简单方法是对AJAX请求的URL使用过滤器。
在下面的示例中,我只是发送HTTP 500响应代码,其响应正文指示会话超时,但您可以轻松地将响应代码和正文设置为更适合您的情况。
package com.myapp.security.authentication;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ExpiredSessionFilter extends GenericFilterBean {
static final String FILTER_APPLIED = "__spring_security_expired_session_filter_applied";
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (request.getAttribute(FILTER_APPLIED) != null) {
chain.doFilter(request, response);
return;
}
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "SESSION_TIMED_OUT");
return;
}
chain.doFilter(request, response);
}
}
答案 1 :(得分:3)
我认为这是一种非常简单的方法。这是我在这个网站上观察到的一系列方法。我写了一篇关于它的博客文章: http://yoyar.com/blog/2012/06/dealing-with-the-spring-security-ajax-session-timeout-problem/
基本思想是使用如上所述的api url前缀(即/ api / secured)以及身份验证入口点。这很简单,也很有效。
这是验证入口点:
package com.yoyar.yaya.config;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class AjaxAwareAuthenticationEntryPoint
extends LoginUrlAuthenticationEntryPoint {
public AjaxAwareAuthenticationEntryPoint(String loginUrl) {
super(loginUrl);
}
@Override
public void commence(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException)
throws IOException, ServletException {
boolean isAjax
= request.getRequestURI().startsWith("/api/secured");
if (isAjax) {
response.sendError(403, "Forbidden");
} else {
super.commence(request, response, authException);
}
}
}
这是你的春天语境中的内容xml:
<bean id="authenticationEntryPoint"
class="com.yoyar.yaya.config.AjaxAwareAuthenticationEntryPoint">
<constructor-arg name="loginUrl" value="/login"/>
</bean>
<security:http auto-config="true"
use-expressions="true"
entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/api/secured/**" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/logout" access="permitAll"/>
<security:intercept-url pattern="/denied" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/" access="permitAll"/>
<security:form-login login-page="/login"
authentication-failure-url="/loginfailed"
default-target-url="/login/success"/>
<security:access-denied-handler error-page="/denied"/>
<security:logout invalidate-session="true"
logout-success-url="/logout/success"
logout-url="/logout"/>
</security:http>
答案 2 :(得分:1)
我在后端使用@Matt的相同解决方案。如果您在前端使用angularJs,请在角度$ http中添加以下拦截器,让浏览器实际重定向到登录页面。
var HttpInterceptorModule = angular.module('httpInterceptor', [])
.config(function ($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
})
.factory('myInterceptor', function ($q) {
return {
'responseError': function(rejection) {
// do something on error
if(rejection.status == 403 || rejection.status == 401) window.location = "login";
return $q.reject(rejection);
}
};
});
请注意,只有在版本1.1.1之后使用AngularJs时才需要下面的行(angularJS从该版本开始删除标题“X-Requested-With”)
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
答案 3 :(得分:1)
看到所有目前的答案现在都已有几年了,我将分享我目前在Spring Boot REST应用程序中工作的解决方案:
[0C40:03A0][2015-12-10T01:39:02]e000: Error 0x80190197: Failed to download http://go.microsoft.com/fwlink/?LinkId=615437&clcid=0x409; will try 2 more times.
[0C40:03A0][2015-12-10T01:39:02]e000: Error 0x80190197: Failed to download http://go.microsoft.com/fwlink/?LinkId=615437&clcid=0x409; will try 1 more times.
[0C40:03A0][2015-12-10T01:39:02]e000: Error 0x8007013d: Failed to format error message.
[0C40:03A0][2015-12-10T01:39:02]i000: Process exit code: 0x80190197 (-2145844841)
这里的基本前提是我覆盖了身份验证入口点,默认情况下是向我不存在的登录页面发出重定向。它现在通过发送401来响应.Spring还隐式创建了它返回的标准错误响应JSON对象。