![](/img/trans.png)
[英]How refresh token works and how last failed http request called again which gave 401…?
[英]How to fix refresh access token from the first http request which gives GET 401 error
問題是,當access token
過期並且我進行任何點擊時,訪問令牌不會刷新。 但是當我第二次點擊時,它會刷新。 第一次點擊,我得到' GET 401 error
'。 對我來說,實際問題是在interceptor
中的任何HTTP請求之前獲取訪問令牌。
我為我的代碼嘗試使用switchMap
來等待訪問令牌,但它沒有用。 你有什么想法我怎么能解決這個問題?
export class DevelopmentInterceptor implements HttpInterceptor {
constructor(
private authService: AuthService,
private router: Router,
private toastr: ToastrService,
private translate: TranslateService
) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const headers = new HttpHeaders({
'Content-Type': 'application/json; charset=utf-8',
'Authorization': `Bearer ${this.authService.getAccessToken()}`
});
let apiReq = null;
if (req.url.indexOf('i18n') >= 0) {
apiReq = req;
} else if (req.url.indexOf('token') >= 0) {
apiReq = req.clone({ url: environment.authServerUrl + `${req.url}` });
} else if (req.url.indexOf('sign-up') >= 0) {
apiReq = req.clone({ url: environment.signupUrl });
} else if (req.url.indexOf('api/users') >= 0 || req.url.indexOf('api/roles') >= 0 || req.url.indexOf('api/permissions') >= 0) {
apiReq = req.clone({ headers: headers, url: environment.authServerUrl + `${req.url}` });
} else {
apiReq = req.clone({ headers: headers, url: environment.backenUrl + `${req.url}` });
}
if (req.url.endsWith('token')) {
return next.handle(apiReq).catch((err: any) => { //<--if error use a catch
if (err instanceof HttpErrorResponse) {
return this.handleError(err);
}
});
} else {
return this.authService.checkExpiry().switchMap( (result) => {
if (result) {
return next.handle(apiReq)
.catch((err: any) => { // <--if error use a catch
if (err instanceof HttpErrorResponse) {
return this.handleError(err);
}
});
}
} )
}
}
private handleError(err: Response | any) {
...
}
}
public checkExpiry() : Observable<any> {
if (!this.cookieService.get('user_id')) {
this.removeTokens(); // not logged in
return Observable.of(true);
} else if (!this.cookieService.check('access_token')) {
if (this.cookieService.check('refresh_token')) {
if (this.secondsTillExpiry('refresh_token') > 0) {
return this.refreshAccessToken().switchMap((data:any) => {
if (data) {
this.saveTokenInCookies(data);
this.updateExpiration(data);
return Observable.of(true);
}
})
} else {
this.router.navigate(['/login']);
this.removeTokens();
return Observable.of(true);
}
}
} else if (this.cookieService.check('access_token') ) {
return Observable.of(true);
}
}
public secondsTillExpiry(tokenMode: string): any {
if (tokenMode == 'access_token') {
return ((new Date(1970, 0,
1).setSeconds(jwt_decode(this.getAccessToken()).exp)) -
(Math.round(Date.now()) / 1000));
} else if (tokenMode == 'refresh_token') {
return ((new Date(1970, 0,
1).setSeconds(jwt_decode(this.getRefreshToken()).exp)) -
(Math.round(Date.now()) / 1000));
}
}
private refreshAccessToken(): Observable<Object> {
const params = 'refresh_token=' + this.getRefreshToken() +
'&grant_type=refresh_token';
return this.http.post(this.authUrl, params, this.getOptions());
}
你也可以在發送CanActivate
任何請求之前檢查過期令牌,如果它是有效令牌,那么用戶可以導航到所需的路由,否則它將被重定向到login
這里是一個處理這個的例子
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
let accesstoken: string = next.queryParams.accesstoken;
if (this.authService.IsAuthenticated) {
let user = this.authService.GetUser();
let CurrentDate = new Date();
let date = CurrentDate.getFullYear() + "-" + (CurrentDate.getMonth() + 1) + "-" + CurrentDate.getDate();
if (user.expire_date) {
if (Date.parse(date) <= Date.parse(user.expire_date)) {
if (accesstoken) {
// if token in url, redirect to url without token :)
if (user.uuid == accesstoken)
this.router.navigateByUrl(window.location.pathname);
// if new token is not the same of current one, Register with new token
else {
return this.authService.checkAccess(accesstoken).pipe(
map(data => {
if (data === true) {
if (accesstoken) {
this.router.navigateByUrl(window.location.pathname);
}
return true;
} else {
this.router.navigate(['/login']);
return false;
}
})
);
}
}
return true;
}
else if (Date.parse(date) > Date.parse(user.expire_date)) {
this.router.navigate(['/login']);
return false;
}
}
}
else {
this.router.navigate(['/login']);
return false;
}
}
你應該根據你的代碼處理它
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.