如何使用spring-security和jQuery处理过期的会话?

via*_*tor 23 authentication ajax jquery spring-security session-timeout

我在我的应用程序中使用spring-security和jQuery.主页使用Ajax动态加载内容到选项卡.一切都很好,但有时我的选项卡中有登录页面,如果我输入凭据,我将被重定向到没有标签的内容页面.

所以我想处理这种情况.我知道有些人使用ajax身份验证,但我不确定它是否适合我,因为它对我来说看起来很复杂,我的应用程序不允许任何访问而无需登录.我想为所有ajax响应编写一个全局处理程序,window.location.reload()如果我们需要进行身份验证,它将会执行.我认为在这种情况下,最好是获取401错误而不是标准登录表单,因为它更容易处理.

所以,

1)是否可以为所有jQuery ajax请求编写全局错误处理程序?

2)我如何自定义spring-security的行为以便为ajax请求发送401错误,但是常规请求像往常一样显示标准登录页面?

3)你可能有更优雅的解决方案吗?请分享.

谢谢.

Mat*_*man 10

这是一种我认为非常简单的方法.这是我在这个网站上观察到的一系列方法.我写了一篇关于它的博客文章: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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是你的spring上下文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>
Run Code Online (Sandbox Code Playgroud)


and*_*o83 9

我使用了以下解决方案.

在spring security中定义了无效的session url

<security:session-management invalid-session-url="/invalidate.do"/>
Run Code Online (Sandbox Code Playgroud)

对于该页面添加了以下控制器

@Controller
public class InvalidateSession
{
    /**
     * This url gets invoked when spring security invalidates session (ie timeout).
     * Specific content indicates ui layer that session has been invalidated and page should be redirected to logout. 
     */
    @RequestMapping(value = "invalidate.do", method = RequestMethod.GET)
    @ResponseBody
    public String invalidateSession() {
        return "invalidSession";
    }
}
Run Code Online (Sandbox Code Playgroud)

并且对于ajax使用ajaxSetup来处理所有ajax请求:

// Checks, if data indicates that session has been invalidated.
// If session is invalidated, page is redirected to logout
   $.ajaxSetup({
    complete: function(xhr, status) {
                if (xhr.responseText == 'invalidSession') {
                    if ($("#colorbox").count > 0) {
                        $("#colorbox").destroy();
                    }
                    window.location = "logout";
                }
            }
        });
Run Code Online (Sandbox Code Playgroud)


Gle*_*tle 2

我通常是这样做的。每次 AJAX 调用时,请在使用之前检查结果。

$.ajax({ type: 'GET',
    url: GetRootUrl() + '/services/dosomething.ashx',
    success: function (data) {
      if (HasErrors(data)) return;

      // process data returned...

    },
    error: function (xmlHttpRequest, textStatus) {
      ShowStatusFailed(xmlHttpRequest);
    }
  });
Run Code Online (Sandbox Code Playgroud)

然后这个HasErrors()功能就像这样,并且可以在所有页面上共享。

function HasErrors(data) {
  // check for redirect to login page
  if (data.search(/login\.aspx/i) != -1) {
    top.location.href = GetRootUrl() + '/login.aspx?lo=TimedOut';
    return true;
  }
  // check for IIS error page
  if (data.search(/Internal Server Error/) != -1) {
    ShowStatusFailed('Server Error.');
    return true;
  }
  // check for our custom error handling page
  if (data.search(/Error.aspx/) != -1) {
    ShowStatusFailed('An error occurred on the server. The Technical Support Team has been provided with the error details.');
    return true;
  }
  return false;
}
Run Code Online (Sandbox Code Playgroud)