问题在于,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());
}
答案 0 :(得分:0)
您还可以在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;
}
}
您应该根据您的代码进行处理