javascript - 我如何在 Angular 4中使用刷新 token

标签 javascript angular laravel api

我已完成授权步骤,并通过 Laravel Passport 获取了访问 token 和刷新 token 。

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

我的主要问题是:

  1. 我应该如何以及何时使用刷新 token 来创建新的访问 token ?
  2. 这应该在后台完成还是用户必须单击按钮来刷新 token ?
  3. 创建新 token 时是否应该重新加载 Angular 页面?

最佳答案

我在我的 Angular 项目中使用 JWT 身份验证,其中 token 由 API 设置。

token 过期时我采取的方法如下所述 -

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

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

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

EDIT - Example of HTTP Interceptor

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回调是做任何你想做的事情的钩子(Hook)。 (在本例中, token 刷新 API 调用)。

我希望这有帮助。 :)

关于javascript - 我如何在 Angular 4中使用刷新 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48077369/

相关文章:

php - 匹配数据透视表中的 id 数组

php - Laravel 从 REST API 检索数据

javascript - 如何使用React从Fantasy Premier League检索授权信息

javascript - 是否可以仅编辑元素内的部分文本内容或 HTML?

javascript - Firebase orderBy 查询返回 null

有 Angular Material : How to set required validator as optional in reactive form

angular - 值未根据三元条件使用正确的值正确初始化

javascript - Microsoft Dynamics 365 CRM WebAPI 弃用替换

angular - 如何从孙子路由到 child

php - Laravel Eloquent 为模型关系设置默认值?