我正在尝试在我的angular 6应用程序中实现刷新令牌功能。对此有很多教程,我正在遵循http://ericsmasal.com/2018/07/02/angular-6-with-jwt-and-refresh-tokens-and-a-little-rxjs-6/和https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/教程来实现。两者基本上有相同的想法。 但是我觉得我面临的问题是由于我们当前的调用刷新令牌功能的结构。以下是说明
1) AuthInterceptor
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private authService: AuthenticationService) { }
isRefreshingToken: boolean = false;
tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
intercept(request: HttpRequest<any>, next: HttpHandler) : Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any> | any> {
return next.handle(this.addTokenToRequest(request, this.authService.getAuthToken()))
.pipe(
catchError(err => {
if (err instanceof HttpErrorResponse) {
switch ((<HttpErrorResponse>err).status) {
case 401:
return this.handle401Error(request, next);
case 400:
return <any>this.authService.logout();
}
} else {
return throwError(err);
}
}));
}
private addTokenToRequest(request: HttpRequest<any>, token: string) : HttpRequest<any> {
return request.clone({ setHeaders: { Authorization: `Bearer ${token}`}});
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if(!this.isRefreshingToken) {
this.isRefreshingToken = true;
// Reset here so that the following requests wait until the token
// comes back from the refreshToken call.
this.tokenSubject.next(null);
return this.authService.refreshToken()
.pipe(
switchMap((user) => {
if(user) {
this.tokenSubject.next(user.accessToken);;
localStorage.setItem('currentUser', JSON.stringify(user));
return next.handle(this.addTokenToRequest(request, user.accessToken));
}
return <any>this.authService.logout();
}),
catchError(err => {
return <any>this.authService.logout();
}),
finalize(() => {
this.isRefreshingToken = false;
})
);
} else {
this.isRefreshingToken = false;
return this.tokenSubject
.pipe(filter(token => token != null),
take(1),
switchMap(token => {
return next.handle(this.addTokenToRequest(request, token));
}));
}
}
}
2) AuthService
我们的刷新令牌服务通过以下规则调用
在该请求的正文中,我们传递了刷新令牌,这是我们从初始登录处收到的
refreshToken() : Observable<any> {
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
let token = currentUser.refreshToken;
let headers = new HttpHeaders();
headers.append('Authorization', 'Basic '+btoa(someid+someotherid));
let body = new URLSearchParams();
body.append('grant_type', 'refresh_token);
body.append('refresh_token', token); <--As commented in no.2
return this.http.post("http://localhost:53217/api/Account/Token/Refresh", body.toString())
.pipe(
map(user => {
if (user && user.accessToken) {
localStorage.setItem('currentUser', JSON.stringify(user));
}
return user;
}));
}
getAuthToken() : string {
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
if(currentUser != null) {
return currentUser.accessToken;
}
return '';
}
观察
以上代码使用本地存储,我们使用cookie。 EG-this.cookieService.get('access_token'),this.cookieService.set('refresh_token','ddsdhsdhsdhsdhs')
简而言之,我的refreshtoken方法应首先使用Basic调用API,然后在收到令牌时调用带有附加新令牌的Bearer的其他API。
请帮助我,因为我被困了几天。 谢谢
答案 0 :(得分:1)
有同样的问题,所以我需要检查拦截器中的标头。
// exempt some paths from authentication
if (req.headers.get('authExempt') === 'true') {
return next.handle(req);
}
这都是假设您致电服务一样
getInfo():Observable<any>{
return this.http.get<any>(API_URL + 'getDocs', httpOptions);
}
和您的httpOptions看起来像
const httpOptions = {
headers: new HttpHeaders({
'authExempt': 'true',
'Content-Type': 'application/json'})
};