验证服务未注销刷新令牌401错误。而是去catchError.ts。应用程序如何处理这个问题。
方案 1.最初使用Basic Authorization标头获取访问令牌。 2.使用访问令牌进行服务器调用。 3.访问toekn过期后,请调用刷新令牌服务。 4.在刷新令牌调用成功时,使用新令牌进行其余的服务调用。 5.在刷新toeken失败时,将返回401错误,但应用程序无法捕获错误并且永远无法注销。
使用Angular 4 Http拦截器
这是拦截器
import { Injectable, Injector } from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse, HttpErrorResponse, HttpClient} from '@angular/common/http';
import * as AppUtils from '../common/app.utils';
import { AuthService } from './auth.service';
import {Observable} from 'rxjs/Rx';
import {
Router,
Event,
NavigationStart, RoutesRecognized, NavigationEnd, NavigationCancel, NavigationError
} from '@angular/router'
import { LoaderService } from '../loader/loader.service'
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
import { EmptyObservable } from 'rxjs/observable/EmptyObservable';
import { catchError, filter, take, switchMap, finalize } from "rxjs/operators";
import { SharedService } from '../common/services/shared.service';
declare var swal: any;
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
isRefreshingToken: boolean = true;
tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
constructor(private inj: Injector, private router: Router) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const auth = this.inj.get(AuthService)
return next.handle(this.addToken(request))
.pipe(
catchError((error, ca) => {
if (error instanceof HttpErrorResponse) {
switch ((<HttpErrorResponse>error).status) {
case 401:
return this.handle401Error(request, next, auth)
default:
return ErrorObservable.create(error);
}
} else {
return ErrorObservable.create(error);
}
})
)
}
addToken(req: HttpRequest<any>): HttpRequest<any> {
let customReq: any;
let client_id = 'test';
let client_secret= 'secret';
let basicheader = btoa(client_id +':'+ client_secret);
if(req.url.indexOf("token?grant_type") < 0 || req.url.indexOf("token?grant_type") == 0){
customReq = req.clone({
headers: req.headers.set('Content-Type', 'application/json')
.set('Authorization','Bearer '+ localStorage.getItem(AppUtils.STORAGE_ACCOUNT_ACCESS_TOKEN))
})
//Set estCode and perscode for Alshif Users
if(localStorage.getItem(AppUtils.ALSHIFA_TRUSTED_LOGIN)!=null && localStorage.getItem(AppUtils.ALSHIFA_TRUSTED_LOGIN)==="Y"){
req.headers.append(AppUtils.ALSHIFA_USER_INFO, localStorage.getItem(AppUtils.DEFAULT_INSTITUTE) +":"+
localStorage.getItem(AppUtils.PERSON_CODE));
}
}else{
customReq = req.clone({
headers: req.headers.set('Authorization','Basic '+ basicheader)
})
}
return customReq;
}
handle400Error(error) {
console.log("400 error");
if (error && error.status === 400 && error.error && error.error.error === 'invalid_grant') {
// If we get a 400 and the error message is 'invalid_grant', the token is no longer valid so logout.
return this.logoutUser();
}
return EmptyObservable.create();
}
handle401Error(req: HttpRequest<any>, next: HttpHandler, auth : any) {
if (this.isRefreshingToken) {
this.isRefreshingToken = false;
let customReq: any;
let client_id = 'test';
let client_secret= 'secret';
let basicheader = btoa(client_id +':'+ client_secret);
auth.refreshToken().subscribe((token) => {
console.log("token " +JSON.stringify(token));
if (token instanceof HttpErrorResponse) {
if (token.status === 401) {
console.log("error");
}
}
if (token) {
localStorage.setItem(AppUtils.STORAGE_ACCOUNT_ACCESS_TOKEN, token["access_token"]);
localStorage.setItem(AppUtils.STORAGE_ACCOUNT_REFRESH_TOKEN, token["refresh_token"]);
localStorage.setItem(AppUtils.STORAGE_ACCOUNT_EXPIRES_IN, token["expires_in"]);
this.tokenSubject.next(token["access_token"]);
return next.handle(this.addToken(req));
}
console.log("refresh failed");
// If we don't get a new token, we are in trouble so logout.
this.logoutUser();
return EmptyObservable.create();
}, (err) => {
console.log("error 2" +err);
// If there is an exception calling 'refreshToken', bad news so logout.
this.logoutUser();
return EmptyObservable.create();
},() => {
console.log("token finally)");
this.isRefreshingToken = true;
});
// )
} else {
console.log("this.tokenSubject "+ this.tokenSubject);
console.log("this.tokenSubjec2 "+ this.tokenSubject.filter(token => token != null));
return this.tokenSubject
.filter(token => token != null)
.take(1)
.switchMap(token => {
return next.handle(this.addToken(req));
});
}
}
logoutUser(){
swal({
title: 'Session Expired',
text: 'your session has been expired please re login',
timer: 5000,
onOpen: () => {
swal.showLoading()
}
}).then((result) => {
if (result.dismiss === 'timer') {
this.router.navigate([AppUtils.BACKEND_API_AUTHENTICATE_PATH]);
window.location.reload();
}
})
localStorage.clear();
this.router.navigate([AppUtils.BACKEND_API_AUTHENTICATE_PATH]);
// window.location.reload();
//return Observable.throw("");
}
这是auth服务类
import { Injectable, Component, EventEmitter } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpClient, HttpResponse, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import 'rxjs/add/operator/map';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/retry';
import * as AppUtils from '../common/app.utils';
import { Router } from '@angular/router';
import { SharedService } from '../common/services/shared.service';
import 'rxjs/add/operator/catch';
declare var swal: any;
@Injectable()
export class AuthService {
cachedRequests: Array<HttpRequest<any>> = [];
constructor(private router: Router, private http : HttpClient) {
}
refreshToken(): Observable<any>{
let client_id = 'irsauth';
let client_secret= 'secret';
let basicheader = btoa(client_id +':'+ client_secret);
let headers = new HttpHeaders();
headers.set('Authorization', 'Basic ' + basicheader);
return this.http.get(AppUtils.REFRESH_TOKEN + localStorage.getItem(AppUtils.STORAGE_ACCOUNT_REFRESH_TOKEN), { headers: headers })
.catch((e: any) => Observable.throw(this.errorHandler(e)))
}
errorHandler(error: any): void {
console.log("auth error")
Observable.throw("");
}
logoutUser(){
localStorage.clear();
this.router.navigate([AppUtils.BACKEND_API_AUTHENTICATE_PATH]);
// window.location.reload();
//return Observable.throw("");
}
}
}
答案 0 :(得分:0)
这对我有用。检查这是否有帮助。基本上它是Angular Http服务的包装器。
callHttpGet(url: string) {
let headers = new Headers({
"Content-Type": "application/json",
"Authorization": "Bearer " +
localStorage.getItem("accessToken")
});
let options = new RequestOptions({ headers: headers });
var me = this;
return this.http.get(url, options)
.catch(initialError => {
if (initialError &&
initialError.status === 401 &&
initialError.json()["message"] === "Token expired") {
// token might be expired, try to refresh token
var tokenObject = new Object();
tokenObject["token"] = localStorage.getItem("refreshToken");
return me.authenticatorService.authenticate(tokenObject)
.flatMap(res => {
return me.http.get(url, me.options);
})
.catch(error => {
if (error &&
error.status === 401 &&
(error.json()["message"] === "Refresh token expired" ||
error.json()["message"] === "Token expired")) {
localStorage.clear();
this.router.navigate(['/login']);
return Observable.throw(error);
}
else {
return Observable.throw(error);
}
});
}
else {
return Observable.throw(initialError);
}
});
}