通过全局捕获401,Angular 2刷新令牌

时间:2017-07-03 12:33:58

标签: angular angular2-services

我想通过从api中捕获401来刷新access_token。我正在使用laravel 5护照。

extended-http.service.ts我的代码中捕获401之后,我的代码不会发送帖子请求以获得更新access_token

我尝试过多种方法,但我唯一可以使用的是以下代码。这段代码的问题是我必须将它添加到我的应用程序内的每个请求中,这是不理想的。我宁愿刷新extended-http.service.ts 401 catch中的令牌。

.catch(initialError => {
    if (initialError && initialError.status === 401) {
        console.log('we got here');
        this.RefreshService.refresh().flatMap((data) => {
            if (localStorage.getItem("access_token") != null) {
                // retry with new token
                return this.getUsers();
            } else {
                return Observable.throw(initialError);
            }
        });
    } else {
        return Observable.throw(initialError);
    }
})

以下代码是我现在要捕获的401.但是当我尝试在捕手内部调用this.refreshToken.refresh();时,我收到以下错误:Cannot instantiate cyclic dependency! Http ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1

// app.module.ts

import { ExtendedHttpService } './services/extended-http.service.ts';
providers: [
    RefreshService
    {provide: Http, useClass: ExtendedHttpService },
]

// refresh.service.ts

import { Injectable } from '@angular/core';
import { Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs, Headers, URLSearchParams } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import * as globals from './../globals';
import { CustomQueryEncoderHelper } from './../shared/helpers';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';


@Injectable()
export class RefreshService {

    constructor(private http: Http) { }
    refresh() {
        let body = new URLSearchParams('', new CustomQueryEncoderHelper());
        body.set('grant_type', 'refresh_token');
        body.set('refresh_token', localStorage.getItem('refresh_token'));
        body.set('client_id', '2');
        body.set('client_secret', 'Crazy secret code');
        let headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded');
        let options = new RequestOptions({ headers: headers });

        return this.http.post(globals.api + 'oauth/token', body, options)
            .map(res => res.json())
            .subscribe((data) => {
                console.log(data);
                localStorage.removeItem("access_token");
                localStorage.removeItem("refresh_token");
                localStorage.removeItem("expires_in");
                localStorage.setItem("access_token", data.access_token);
                localStorage.setItem("refresh_token", data.refresh_token);
                localStorage.setItem("expires_in", data.expires_in);
                location.reload();
            },
            (error) => {
                Observable.throw(error);
            }
            );
    }
}

//扩展http.service.ts

import { Injectable } from '@angular/core';
import { Request, XHRBackend, RequestOptions, Response, Http, 
RequestOptionsArgs, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

@Injectable()
export class ExtendedHttpService extends Http {

    constructor(backend: XHRBackend, defaultOptions: RequestOptions) {
        super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
        return super.request(url, options).catch((error: Response) => {
            if ((error.status === 401 || error.status === 403) &&
               (window.location.href.match(/\?/g) || []).length < 2) {
                console.log('The authentication session expires or the user is not authorised. Force refresh of the current page.');
                this.refreshToken.refresh(); // Doesn't work
                // How can i refresh token here?
        }
            return Observable.throw(error);
        });
    }
}

所以回顾一下我想在extended.service.ts 401 catch中刷新令牌。但我不知道我应该如何让它发挥作用。请帮忙!

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,但是我找到了解决问题的方法。

import { Injectable, Injector } from '@angular/core';
constructor(public toastr: ToastrService, public toastrConfig: ToastrConfig, private router: Router,
    private injector: Injector, private cookieService: CookieService) {
    toastrConfig.closeButton = true;
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.ingestionService = this.injector.get(IngestionService);
// HERE i create an instance of that.
}