Angular 8 Intercept 调用刷新令牌 [英] Angular 8 Intercept call to refresh token

查看:21
本文介绍了Angular 8 Intercept 调用刷新令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果当前访问令牌已过期,我正在尝试刷新访问令牌.

I am trying to refresh access token if current access token is expired.

我一次发送多个请求,我想创建一种队列,这样其他请求就不会请求刷新令牌路由.

I am sending multiple requests at one time and I want to make a kind of a queue, so other requests won't request refreshing token route.

我在谷歌上搜索了一些最佳实践和示例,并找到了以下针对 Angular 6 和 rxjs v6 的解决方案,该解决方案使用 BehaviourSubject 和 switchMaps.(见附件代码)

I've googled some best practises and examples and found out the following solution for Angular 6 and rxjs v6, which is using BehaviourSubject and switchMaps. (please see attached code)

但是我使用的是 Angular 8 (8.1) 和 rxjs v6.4,这个解决方案对我不起作用.

However I am using Angular 8 (8.1) and rxjs v6.4 and this solution does not work for me.

它根本无法到达 this.authService.requestAccessToken().pipe 中的 switchMap.(使用 console.log 测试)

It simply does not reach switchMap in this.authService.requestAccessToken().pipe. (Tested using console.log)

但是,如果我评论 return this.refreshTokenSubject.pipe 并返回 next.handle(request) 它到达那个 switchMap,但我的其他请求都失败了.

However if I comment return this.refreshTokenSubject.pipe and return next.handle(request) it reaches that switchMap, but my other requests are failed.

您知道是否有任何更改,还是我应该尝试以其他方式进行更改?

Do you know if anything has been changed or should I try doing this in another way?

  • 令牌拦截器
    import { Injectable } from '@angular/core';
    import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
    import { AuthService } from './auth.service';
    import { Observable, BehaviorSubject, Subject } from 'rxjs';
    import { switchMap, take, filter } from 'rxjs/operators';
    @Injectable()
    export class TokenInterceptor implements HttpInterceptor {
        private refreshTokenInProgress = false;
        private refreshTokenSubject: Subject<any> = new BehaviorSubject<any>(null);

        constructor(public authService: AuthService) { }
        intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

            const accessExpired = this.authService.isAccessTokenExpired();
            const refreshExpired = this.authService.isRefreshTokenExpired();

            if (accessExpired && refreshExpired) {
                return next.handle(request);
            }
            if (accessExpired && !refreshExpired) {
                if (!this.refreshTokenInProgress) {
                    this.refreshTokenInProgress = true;
                    this.refreshTokenSubject.next(null);
                    return this.authService.requestAccessToken().pipe(
                        switchMap((authResponse) => {
                            this.authService.saveToken(AuthService.TOKEN_NAME, authResponse.accessToken);
                            this.authService.saveToken(AuthService.REFRESH_TOKEN_NAME, authResponse.refreshToken);
                            this.refreshTokenInProgress = false;
                            this.refreshTokenSubject.next(authResponse.refreshToken);
                            return next.handle(this.injectToken(request));
                        }),
                    );
                } else {
                    return this.refreshTokenSubject.pipe(
                        filter(result => result !== null),
                        take(1),
                        switchMap((res) => {
                            return next.handle(this.injectToken(request))
                        })
                    );
                }
            }

            if (!accessExpired) {
                return next.handle(this.injectToken(request));
            }
        }

        injectToken(request: HttpRequest<any>) {
            const token = this.authService.getToken(AuthService.TOKEN_NAME);
            return request.clone({
                setHeaders: {
                    Authorization: `Bearer ${token}`
                }
            });
        }
    }

  • requestAccessToken
  •     requestAccessToken(): Observable<any> {
            const refreshToken = this.getToken(AuthService.REFRESH_TOKEN_NAME);
            return this.http.post(`${this.basePath}/auth/refresh`, { refreshToken });
        }
    

    <小时>

    更新 1

    所以我使用这些资源来编写我的拦截器:


    UPD 1

    So I used these sources to write my interceptor:

    • https://itnext.io/angular-tutorial-implement-refresh-token-with-httpinterceptor-bfa27b966f57 (Angular 4 solution, I believe it edpends on rxjs version)

    https://github.com/melcor76/interceptors/blob/master/src/app/interceptors/auth.interceptor.ts

    我已经从拦截器范围中排除了 refresh 请求,现在它正在工作感谢@JBNizet

    I've excluded refresh request from interceptor scope and now it's working Thanks to @JBNizet

    推荐答案

    我已经从拦截器范围中排除了刷新请求,现在它可以工作了.我已经做了一个临时修复,以查看它以最快的方式工作.

    I've excluded refresh request from interceptor scope and now it's working. I've made a temporary fix in order to see it's working in the fastest way.

    现在我的 TokenInterceptor 看起来像:

    Now my TokenInterceptor looks like:

    import { Injectable } from '@angular/core';
    import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
    import { AuthService } from './auth.service';
    import { Observable, BehaviorSubject, Subject } from 'rxjs';
    import { switchMap, take, filter } from 'rxjs/operators';
    @Injectable()
    export class TokenInterceptor implements HttpInterceptor {
        private refreshTokenInProgress = false;
        private refreshTokenSubject: Subject<any> = new BehaviorSubject<any>(null);
    
        constructor(public authService: AuthService) { }
        intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            if (request.url.indexOf('refresh') !== -1) {
                return next.handle(request);
            }
    
            const accessExpired = this.authService.isAccessTokenExpired();
            const refreshExpired = this.authService.isRefreshTokenExpired();
    
            if (accessExpired && refreshExpired) {
                return next.handle(request);
            }
            if (accessExpired && !refreshExpired) {
                if (!this.refreshTokenInProgress) {
                    this.refreshTokenInProgress = true;
                    this.refreshTokenSubject.next(null);
                    return this.authService.requestAccessToken().pipe(
                        switchMap((authResponse) => {
                            this.authService.saveToken(AuthService.TOKEN_NAME, authResponse.accessToken);
                            this.authService.saveToken(AuthService.REFRESH_TOKEN_NAME, authResponse.refreshToken);
                            this.refreshTokenInProgress = false;
                            this.refreshTokenSubject.next(authResponse.refreshToken);
                            return next.handle(this.injectToken(request));
                        }),
                    );
                } else {
                    return this.refreshTokenSubject.pipe(
                        filter(result => result !== null),
                        take(1),
                        switchMap((res) => {
                            return next.handle(this.injectToken(request))
                        })
                    );
                }
            }
    
            if (!accessExpired) {
                return next.handle(this.injectToken(request));
            }
        }
    
        injectToken(request: HttpRequest<any>) {
            const token = this.authService.getToken(AuthService.TOKEN_NAME);
            return request.clone({
                setHeaders: {
                    Authorization: `Bearer ${token}`
                }
            });
        }
    }
    

    感谢@JBNizet

    这篇关于Angular 8 Intercept 调用刷新令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆