当前位置: 首页 > 知识库问答 >
问题:

JWT过期令牌处理与角度拦截器保持刷新

公西俊能
2023-03-14

我在Angular中有一个拦截器,我使用它在令牌过期时刷新令牌,但当令牌成功刷新时,应用程序似乎会陷入对API无止境的401个错误调用中。当我单步执行代码时,令牌确实会在过期时刷新,但随后会尝试重复刷新。

我还应该注意,在再次单击按钮并再次调用API时,应用程序将获得新的令牌,并在随后正常工作。不过,我希望在没有这么多控制台错误的情况下工作。

import { Injectable, Injector } from "@angular/core";
import { Router } from "@angular/router";
import {
    HttpClient,
    HttpHandler, HttpEvent, HttpInterceptor,
    HttpRequest, HttpResponse, HttpErrorResponse
} from "@angular/common/http";
import { AuthService } from "./auth.service";
import { Observable } from "rxjs/Observable";

@Injectable()
export class AuthResponseInterceptor implements HttpInterceptor {

    currentRequest: HttpRequest<any>;
    auth: AuthService;

    constructor(
        private injector: Injector,
        private router: Router
    ) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        this.auth = this.injector.get(AuthService);
        var token = (this.auth.isLoggedIn()) ? this.auth.getAuth()!.token : null;

        if (token) {
            // save current request
            this.currentRequest = request;

            return next.handle(request)
                .do((event: HttpEvent<any>) => {
                    if (event instanceof HttpResponse) {
                        // do nothing
                    }
                })
                .catch(error => {
                    return this.handleError(error)
                });
        }
        else {
            return next.handle(request);
        }
    }

    handleError(err: any) {
        if (err instanceof HttpErrorResponse) {
            if (err.status === 401) {
                // JWT token might be expired:
                // try to get a new one using refresh token
                console.log("Token expired. Attempting refresh...");
                this.auth.refreshToken()
                    .subscribe(res => {
                        if (res) {
                            // refresh token successful
                            console.log("refresh token successful");

                            // re-submit the failed request
                            var http = this.injector.get(HttpClient);
                            http.request(this.currentRequest).subscribe(
                                (result: any) => {
                                    console.log(this.currentRequest);
                                }, (error: any) => console.error(error)
                            );
                        }
                        else {
                            // refresh token failed
                            console.log("refresh token failed");

                            // erase current token
                            this.auth.logout();

                            // redirect to login page
                            this.router.navigate(["login"]);
                        }
                    }, error => console.log(error));
            }
        }
        return Observable.throw(err);
    }
}
import { Injectable, Injector } from "@angular/core";
import { Router } from "@angular/router";
import {
    HttpClient,
    HttpHandler, HttpEvent, HttpInterceptor,
    HttpRequest, HttpResponse, HttpErrorResponse, HttpHeaders
} from "@angular/common/http";
import { AuthService } from "./auth.service";
import { Observable, Subject } from "rxjs";

@Injectable()
export class AuthResponseInterceptor implements HttpInterceptor {


    auth: AuthService;
    currentRequest: HttpRequest<any>;


    constructor(
        private injector: Injector,
        private router: Router
    ) { }


    logout() {
        this.auth.logout();
        this.router.navigate(["login"]);
    }


    intercept(
        request: HttpRequest<any>,
        next: HttpHandler): Observable<HttpEvent<any>> {


        this.auth = this.injector.get(AuthService);
        let token = (this.auth.isLoggedIn()) ? this.auth.getAuth()!.token : null;




        this.currentRequest = request;



        return next.handle(request).
            catch((error) => {
                if (error instanceof HttpErrorResponse && error.status === 401) {
                    return this.auth.refreshToken()

                        .switchMap(() => {
                            let token = (Response) ? this.auth.getAuth() : null;
                            console.log(token);

                            if (token) {
                                this.currentRequest = request.clone({
                                    setHeaders: {
                                        Authorization: `Bearer ${token.token}`
                                    }
                                });
                            }

                            return next.handle(this.currentRequest);

                        }).
                        catch((e) => {
                            this.logout();
                            console.error(e);
                            return Observable.empty();
                        });
                }

                return Observable.throw(error);

            });
    }


}
constructor(private http: HttpClient,
        @Inject(PLATFORM_ID) private platformId: any) {
    }

    // performs the login
    login(username: string, password: string): Observable<boolean> {
        var url = "api/token/auth";
        var data = {
            username: username,
            password: password,
            client_id: this.clientId,
            // required when signing up with username/password
            grant_type: "password",
            // space-separated list of scopes for which the token is issued
            scope: "offline_access profile email"
        };

        return this.getAuthFromServer(url, data);
    }

    // try to refresh token
    refreshToken(): Observable<boolean> {
        var url = "api/token/auth";
        var data = {
            client_id: this.clientId,
            // required when signing up with username/password
            grant_type: "refresh_token",
            refresh_token: this.getAuth()!.refresh_token,
            // space-separated list of scopes for which the token is issued
            scope: "offline_access profile email"
        };

        return this.getAuthFromServer(url, data);
    }

    // retrieve the access & refresh tokens from the server
    getAuthFromServer(url: string, data: any): Observable<boolean> {
        return this.http.post<TokenResponse>(url, data)
            .map((res) => {
                let token = res && res.token;
                // if the token is there, login has been successful
                if (token) {
                    // store username and jwt token
                    this.setAuth(res);
                    // successful login
                    return true;
                }

                // failed login
                return Observable.throw('Unauthorized');
            })
            .catch(error => {
                return new Observable<any>(error);
            });
    }

    // performs the logout
    logout(): boolean {
        this.setAuth(null);
        return true;
    }

    // Persist auth into localStorage or removes it if a NULL argument is given
    setAuth(auth: TokenResponse | null): boolean {
        if (isPlatformBrowser(this.platformId)) {
            if (auth) {
                localStorage.setItem(
                    this.authKey,
                    JSON.stringify(auth));
            }
            else {
                localStorage.removeItem(this.authKey);
            }
        }
        return true;
    }

    // Retrieves the auth JSON object (or NULL if none)
    getAuth(): TokenResponse | null {
        if (isPlatformBrowser(this.platformId)) {
            var i = localStorage.getItem(this.authKey);
            if (i) {
                return JSON.parse(i);
            }
        }
        return null;
    }

    // Returns TRUE if the user is logged in, FALSE otherwise.
    isLoggedIn(): boolean {
        if (isPlatformBrowser(this.platformId)) {
            return localStorage.getItem(this.authKey) != null;
        }
        return false;
    }

共有1个答案

高明辉
2023-03-14
return this.auth.refreshToken(response:any)
        //response can be true or null
        let token=(response)?this.auth.getAuth():null;
        //In token we have an object of type TokenResponse
        console.log(token)
        .switchMap(() => {
            if (token) {
               this.currentRequest = request.clone({
                    setHeaders: {  //I think it's toke.token
                         Authorization: `Bearer ${token.token}`
                      }
               });
....

注意:尝试将“var”改为“let”注意2:一开始你有

var token = (this.auth.isLoggedIn()) ? this.auth.getAuth()!.token : null;
//    May be  remove "!"?
let  token = (this.auth.isLoggedIn()) ? this.auth.getAuth().token : null;
 类似资料:
  • 我需要(在拦截器类中)对403禁止的HTTP状态(获取/刷新)JWT令牌作出反应,并使用新令牌重试请求。 在下面的代码中,当服务器返回错误响应时,它将转到成功回调(而不是像我预期的那样进入错误回调),事件是typeof object(这在错误响应的反应中是无用的)。事件对象如下所示:{type:0}。 问题: -当我需要刷新accessToken并重试http请求时,如何在HttpIntercep

  • 我已经实现了 JWT 和刷新令牌流。当我过去实现这一点时,我的做法略有不同,主要是刷新令牌是在正文中发送的。 但是现在我做了不同的事情,我必须通过授权标头发送访问令牌,但是我的拦截器代码不想切换不记名令牌。如何修复,如果我想刷新,我实际上使用刷新令牌作为不记名令牌,而不是过期的访问令牌? 我还尝试在post请求中将HTTP标头设置为授权承载令牌

  • 我正在从事一个spring boot angular项目,其中用户从angular前端登录到spring boot上的身份验证api,该api返回一个JWT令牌。我还在Angular上设置了一个拦截器,该拦截器为所有请求附加带有JWT令牌的授权头。 我正在寻找一种拦截angualar请求的方法,这样当spring boot在JWT令牌过期后抛出401错误时,Angular前端将尝试使用过期的JWT

  • 我有一个使用express api的react应用程序。我正在尝试在访问令牌过期时刷新令牌。我正在使用axios拦截器来实现这一成就。 它卡在某个地方了。我使用console.log来调试它。从控制台; 发布http://localhost:5000/api/auth/token?null 401(未经授权) 之后什么都没发生。我该怎么办?谢谢你的帮助

  • 本文向大家介绍Vue 拦截器对token过期处理方法,包括了Vue 拦截器对token过期处理方法的使用技巧和注意事项,需要的朋友参考一下 最近在做的一个项目,需要每个http请求下 都要添加token,这样无疑是增加了工作量。而vue 拦截器interceptors正好可以解决我们的需求。 以上这篇Vue 拦截器对token过期处理方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望

  • 我正在构建一个移动应用程序,并且正在使用JWT进行身份验证。 最好的方法似乎是将JWT访问令牌与刷新令牌配对,这样我就可以根据需要频繁地使访问令牌过期。 刷新令牌是什么样子的?是随机字符串吗?那串加密了吗?是另一个JWT吗? 刷新令牌将存储在用户模型的数据库中以便访问,对吗?在这种情况下似乎应该加密 在用户登录后,我是否会将刷新令牌发送回,然后让客户端访问单独的路由来检索访问令牌?

  • 问题内容: 我正在使用AngularJS构建SPA,并与服务(JAVA)通信。 当用户发送其用户名/密码时,服务会同时发送回:Acces令牌和Refresh令牌。我正在尝试处理:如果收到状态为401的响应,请发送回刷新令牌,然后再次发送您的上一个请求。我试图通过包含$ http来做到这一点,但是angular不允许我在此拦截器中包含它。有什么方法可以使用我正在接收的响应参数来重新创建原始请求吗?