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);
            }
          };
        });
});

 

转载于:https://www.cnblogs.com/phoenix-smile/p/5681271.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Angular项目中,可以通过路由守卫来实现登录功能。具体来说,可以创建一个名为`AuthGuard`的守卫,在守卫中判断用户是否已经登录,如果已经登录则允许路由跳转,否则禁止路由跳转。在登录失败的情况下,可以将用户重定向到登录面,以便再次输入正确的登录信息。 下面是一个简单的示例: 1. 创建 `AuthGuard` 守卫 ```typescript import { Injectable } from '@angular/core'; import { CanActivate, Router } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate(): boolean { if (this.authService.isLoggedIn()) { return true; } else { this.router.navigate(['/login']); return false; } } } ``` 2. 在路由配置中使用 `AuthGuard` 守卫 ```typescript import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { LoginComponent } from './login/login.component'; import { AuthGuard } from './auth.guard'; const appRoutes: Routes = [ { path: '', component: HomeComponent, canActivate: [AuthGuard] }, { path: 'login', component: LoginComponent }, ]; @NgModule({ imports: [ RouterModule.forRoot(appRoutes) ], exports: [ RouterModule ] }) export class AppRoutingModule { } ``` 在上面的代码中,`HomeComponent` 是需要登录后才能访问的组件,因此使用 `canActivate` 属性设置了 `AuthGuard` 守卫。如果用户已经登录,则可以访问该组件;否则将被重定向到登录面。`LoginComponent` 则是登录面的组件。 3. 创建 `AuthService` 服务 在上面的代码中,`AuthGuard` 守卫中使用了 `AuthService` 服务的 `isLoggedIn()` 方法来判断用户是否已经登录。下面是 `AuthService` 服务的一个简单实现: ```typescript import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { private isLoggedInFlag = false; constructor() { } login(username: string, password: string): boolean { // TODO: 实现登录逻辑 // 如果登录成功,则将 isLoggedInFlag 设置为 true // 否则设置为 false return this.isLoggedInFlag; } logout(): void { this.isLoggedInFlag = false; } isLoggedIn(): boolean { return this.isLoggedInFlag; } } ``` 在上面的代码中,`login()` 方法是登录的方法,如果登录成功则将 `isLoggedInFlag` 设置为 `true`,否则设置为 `false`。`logout()` 方法用于退出登录,将 `isLoggedInFlag` 设置为 `false`。`isLoggedIn()` 方法用于判断用户是否已经登录。 注意:上面的代码仅供参考,具体的实现需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值