【发布时间】:2020-08-25 19:41:09
【问题描述】:
我正在使用 jwt 进行身份验证。我在提神方面遇到了麻烦。可能我认为这是由于我在 rxjs 可观察对象和操作符方面缺乏经验。我使用 auth.service.ts
的这些方法从后端获取刷新令牌 getNewAccessToken(refreshToken: string){
return this.httpClient.post<Token>(`${this.baseService.baseUrl}auth-token-refresh/`, { refresh: refreshToken }, this.baseService.httpOptions).pipe(
map((response:Token) => {
this.cookieService.set(environment.tokenAccessName, response.access, null, '/', null, null, 'Strict');
return response;
}
));
}
getAuthToken() {
return this.cookieService.get(this.tokenAccessName);
}
getRefreshToken() {
return this.cookieService.get(this.tokenRefreshName);
}
hasValidToken() {
if (this.getAuthToken())
return !helper.isTokenExpired(this.getAuthToken());
else
return false;
}
这是我的拦截器auth-interceptor.ts
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpErrorResponse
} from '@angular/common/http';
import { AuthService } from '../services/auth.service';
import { throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { Token } from '../models/token';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) {}
intercept(request: HttpRequest<any>, next: HttpHandler) {
const authToken = this.authService.getAuthToken();
if (authToken) {
if (this.authService.hasValidToken()) {
request = this.addAuthenticationToken(request);
}
}
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
} else {
return throwError(error);
}
}));
}
handle401Error(request: HttpRequest<any>, next: HttpHandler) {
const refreshToken = this.authService.getRefreshToken();
this.authService.getNewAccessToken(refreshToken).subscribe(
(response: Token) => {
this.addAuthenticationToken(request);
return next.handle(request);
},
error => throwError(error)
)
}
addAuthenticationToken(request: HttpRequest<any>) {
const authToken = this.authService.getAuthToken();
return request.clone({
headers: request.headers.set('Authorization', 'Bearer ' + authToken),
});
}
}
我的ide显示如下错误
Property 'intercept' in type 'AuthInterceptor' is not assignable to the same property in base type 'HttpInterceptor'.
Type '(request: HttpRequest<any>, next: HttpHandler) => Observable<unknown>' is not assignable to type '(req: HttpRequest<any>, next: HttpHandler) => Observable<HttpEvent<any>>'.
Type 'Observable<unknown>' is not assignable to type 'Observable<HttpEvent<any>>'.
Type 'unknown' is not assignable to type 'HttpEvent<any>'.
Property 'type' is missing in type '{}' but required in type 'HttpUserEvent<any>'.
还有
Argument of type '(error: any) => void | Observable<never>' is not assignable to parameter of type '(err: any, caught: Observable<HttpEvent<any>>) => ObservableInput<any>'.
Type 'void | Observable<never>' is not assignable to type 'ObservableInput<any>'.
Type 'void' is not assignable to type 'ObservableInput<any>'.
我想我可能弄错了返回类型,但我不知道出了什么问题
【问题讨论】:
-
我们可以得到你的 auth-interceptor 的内容吗?
-
@htn 谢谢,我没有注意到我粘贴了错误的代码
-
我了解您的意图。很容易找出问题所在:handle401Error 应该返回一个
Observable(此处为空)。第一个return throwError(error)应替换为throw error;。对于第二个,订阅的 errorHandler 中不要返回任何内容。但是,要给您正确的答案并不容易:当出现 401 错误时,请尝试在重播请求之前刷新令牌(如果您没有正确执行,您可能会陷入无限循环) -
抛出错误; 不会改变任何东西。我不断收到同样的错误。说到401响应时刷新token的策略,看了很多教程解释,觉得是对的
-
这是一种正确的做法,但重试很复杂。一个更简单的处理方法是:本地检查令牌有效性,如果需要刷新,并在收到 401 时注销。好吧,我重新阅读了您的代码:我们不会在收到 401 时发送 refreshToken,但您使用它来生成另一个令牌...我建议您找到一个可行的示例。
标签: angular rxjs jwt angular-httpclient angular-http-interceptors