如何在角度4中使用刷新令牌

问题描述 投票:0回答:1

我已经完成了授权步骤并获得了Laravel Passport的访问令牌和刷新令牌。

我的Angular前端和Laravel后端工作正常。

我的主要问题是:

  1. 我应该如何以及何时使用刷新令牌来创建新的访问令牌?
  2. 这应该在后台完成还是用户必须单击按钮刷新令牌?
  3. 是否应在创建新令牌时重新加载Angular页面?
javascript angular laravel api
1个回答
1
投票

我在我的角度项目中使用JWT身份验证,其中令牌由API设置。

我在令牌过期时采取的方法如下所述 -

  1. 公开一个新的API,它将获取一个过期的令牌并返回新创建的令牌。
  2. API应检查每个REST API调用中的令牌过期。
  3. 如果令牌过期,API应返回状态(根据标准,498 - 过期/无效)。
  4. 在angular中,创建一个服务层(令牌刷新),它将每个API调用委托给服务器(内部使用http服务)。
  5. 此服务的工作是检查API响应的状态(如果它是498)并在内部进行额外调用以刷新令牌。
  6. 然后,服务可以使用新创建的令牌重新启动原始呼叫以获得响应。
  7. 所有api服务都会调用令牌刷新器来获取响应。

在更广泛的层面上,令牌刷新是默认http服务的包装器,它执行额外的检查。

这将避免恼人的页面加载并使应用程序更快。

编辑 - HTTP拦截器的示例

import { Injectable } from "@angular/core";
import { XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Http, Headers } from "@angular/http";
import { Store } from "@ngrx/store";
import { Observable } from "rxjs/Rx";
import { Observer } from "rxjs/Observer";
import { Response as ApiResponse } from "../../models/base/response.model";
import { ToastModel } from "../../redux/app-reducers";
import { ReducerActions } from "../../redux/reducer-actions";

@Injectable()
export class HttpInterceptor extends Http {
    constructor(private _XHRBackend: XHRBackend,
        private _RequestOptions: RequestOptions,
        private _ToastStore: Store<ToastModel>,
        private _LoaderStore: Store<boolean>) {
        super(_XHRBackend, _RequestOptions);
    }

    public request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
        return this.handleResponse(super.request(url, options));
    }

    public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
        this.beforeRequest(url);
        return super.get(url, this.getRequestOptionArgs(options));
    }

    public post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
        this.beforeRequest(url, body);
        return super.post(url, body, this.getRequestOptionArgs(options));
    }

    public put(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
        this.beforeRequest(url, body);
        return super.put(url, body, this.getRequestOptionArgs(options));
    }

    public delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
        this.beforeRequest(url);
        return super.delete(url, this.getRequestOptionArgs(options));
    }

    private getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
        if (options == null) {
            options = new RequestOptions();
        }
        if (options.headers == null) {
            options.headers = new Headers();
        }
        options.headers.append('Content-Type', 'application/json');

        return options;
    }

    private handleResponse(response: Observable<Response>): Observable<Response> {
        return response
            .catch(this.onCatch)
            .do(this.onSuccess.bind(this), this.onError.bind(this))
            .finally(this.afterResponse.bind(this));
    }

    private beforeRequest(url: string, body?: string): void {
        this._LoaderStore.dispatch({ type: ReducerActions.Loader.Set, payload: true });
    }

    private afterResponse(): void {
        this._LoaderStore.dispatch({ type: ReducerActions.Loader.Set, payload: false });
    }

    private onCatch(error: any, caught: Observable<Response>): Observable<Response> {
        console.log("interceptor catch called");
        return Observable.throw(error);
    }

    private onSuccess(res: Response): void {
        let response: ApiResponse<any> = res.json();
        if (!response.message) {
            return;
        }
        let toast: ToastModel = {
            text: response.message,
            duration: 5000,
            type: "success"
        };
        this._ToastStore.dispatch({ type: ReducerActions.Toast.Update, payload: toast });
    }

    private onError(error: any): void {
        let toast: ToastModel = {
            text: "Error occurred!",
            duration: 5000,
            type: "failure"
        };
        this._ToastStore.dispatch({ type: ReducerActions.Toast.Update, payload: toast });
    }
}

在上面的例子中,handleResponse回调是做你想做的任何事情的钩子。 (在这种情况下,令牌刷新API调用)。

我希望这有帮助。 :)

© www.soinside.com 2019 - 2024. All rights reserved.