Spring Security登錄超時,angular ajax請求出錯自動跳轉至登錄頁(jQuery也適用)


  公司開發采用Spring Security+AngualerJS框架,在session過期之后,ajax請求會直接出錯。本文介紹如何實現出錯情況下自動跳轉至登錄頁。

  整體思路是,session過期后,ajax請求返回401 unauthentication錯誤,前端對$http服務添加攔截器,對401錯誤進行跳轉處理,跳轉至登錄頁。

  由於session過期,需要驗證的請求(不論是不是ajax請求)會返回302重定向,我們先配置spring security使之能對ajax請求返回401錯誤。如下:

  實現自定義的RequestMatcher,當請求是ajax請求即匹配上(angular默認不會帶上X-Requested-With,這里通過Accept進行判斷,也可以在前端對ajax請求添加X-Requested-With頭):

public static class AjaxRequestMatcher implements RequestMatcher {
    @Override
    public boolean matches(HttpServletRequest request) {
        return "XMLHttpRequest".equals(request.getHeader("X-Requested-With")) ||
                request.getHeader("Accept") != null && 
                    request.getHeader("Accept").contains("application/json");
    }
}

  實現自定義的AuthenticationEntryPoint,返回401錯誤:

@Component
public class AjaxAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException, ServletException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    }

}

  配置錯誤處理,對ajax請求使用AjaxAuthenticationEntryPoint(

  .exceptionHandling()
        .defaultAuthenticationEntryPointFor(authenticationEntryPoint, new AjaxRequestMatcher())):

    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;
    
    protected void configure(HttpSecurity http) throws Exception {
        http
            .headers()
                .cacheControl()
                .and()
            .authorizeRequests()
                .antMatchers(
                    "/login",
                    "/css/**",
                    "/img/**",
                    "/js/**",
                    "/partial/**",
                    "/script/**",
                    "/upload/**",
                    "/plugin/**").permitAll()
                .antMatchers("/**")
                .authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .defaultSuccessUrl("/app.html", true)
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/login")
                .and()
            .exceptionHandling()
                .defaultAuthenticationEntryPointFor(authenticationEntryPoint, new AjaxRequestMatcher())
                .and()
            .csrf().disable();
    }

  前端,添加攔截器:

angular.module('app', [])
.config(function($httpProvider) {
    $httpProvider.interceptors.push(function($q, $window) {
          return {
            // optional method
            'request': function(config) {
              // do something on success
              return config;
            },
            // optional method
           'requestError': function(rejection) {
              // do something on error
              if (canRecover(rejection)) {
                return responseOrNewPromise
              }
              return $q.reject(rejection);
            },
            // optional method
            'response': function(response) {
              // do something on success
              return response;
            },
            // optional method
           'responseError': function(rejection) {
              // do something on error
              if (rejection.status === 401) {
//                return responseOrNewPromise
                  console.log('401');
                  $window.location.href = 'login?expired';
              }
              return $q.reject(rejection);
            }
          };
        });
});

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM