angular - 使用 Angular 6 拦截器刷新令牌
问题描述
我正在尝试在我的 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)认证服务
我们的刷新令牌服务通过以下规则调用
- 要调用 refreshtoken,我们发送一个带有 Basic 标头和值 btoa(someid + someotherid) 的请求
在该请求的正文中,我们传递了刷新令牌,我们从初始登录中收到
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 ''; }
观察
- 它在 auth 服务中调用 refreshtoken 方法,然后再次从 authinterceptor 传递到 else 块并调用 addTokenToRequest()。因此,它没有将标头添加为 Basic,而是附加 Bearer 并再次发回 401 错误。
上面的代码使用了localstorage,我们使用的是cookies。EG - this.cookieService.get('access_token') , this.cookieService.set('refresh_token', 'ddsdhsdhsdhsdhs')
简而言之,我的 refreshtoken 方法应该首先使用 Basic 调用 API,然后在收到令牌时调用其他 API,并在 Bearer 中附加新令牌。
请帮助我,因为我被困了几天。谢谢
解决方案
有同样的问题,所以我需要检查拦截器中的标题。
// 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'})
};
推荐阅读
- mysql - Mysql查询以在条件下选择不同的记录?
- python - 如何在熊猫中组合 groupby(s)?
- c++ - 使用 C++ 在 JNI 调用 API 中创建对子对象的父引用
- babeljs - Babel7 不使用 --ignore 排除文件/文件夹
- r - R中是否有任何网站内容监控包?
- powershell - Powershell HasUniqueRoleAssignments 检查子站点是否具有唯一权限。
- django - Django ORM Count 组和子组
- haskell - Haskell 拆分列表
- android - 当媒体播放器在服务类中停止时应用程序停止工作
- android - android:回收器视图适配器