我正在使用两个JWT令牌-刷新令牌(7天后过期)和访问令牌(15分钟后过期)。它们存储在httpOnly cookie中,可以通过服务器访问。刷新方法对新令牌进行签名并将其存储在cookie中。我需要检查每个请求之后这些令牌是否已过期:
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService, private cookieService: CookieService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const expirationToken = this.cookieService.get('tokenexp'); // access token expiration
const expirationTokenRefresh = this.cookieService.get('tokenrefexp'); // refresh expiration
// refresh token -> access token -> original request
return of(Number(expirationTokenRefresh) < Date.now()).pipe(
mergeMap(expire => expire
? this.authService.refreshTokenRefresh()
: of(Number(expirationToken) < Date.now())
),
mergeMap(expire => expire
? this.authService.refreshToken()
: of(true)
),
mergeMap(ok => next.handle(req.clone({ withCredentials: true })))
);
}
}
// auth service
refreshToken() {
return this.http.get(`${BACKEND_URL}/refreshtoken`);
}
refreshTokenRefresh() {
return this.http.get(`${BACKEND_URL}/refreshtokenref`);
}
我可能会发送一个请求以刷新令牌,然后发送另一个请求以刷新第二个令牌,最后发送具有更新cookie的原始请求。总之,我可能需要在原始请求之前发送请求。
问题是:每次发出请求时,都会有一个循环到AuthInterceptor
的请求。请求一个和两个(令牌)不应调用AuthInterceptor
。
答案 0 :(得分:1)
如果请求网址是针对令牌的,请执行条件检查以跳过拦截器。
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService, private cookieService: CookieService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if(req.url===`${BACKEND_URL}/refreshtoken` || req.url ===`${BACKEND_URL}/refreshtokenref`)
return next.handle(req.clone({ withCredentials: true }))
const expirationToken = this.cookieService.get('tokenexp'); // access token expiration
const expirationTokenRefresh = this.cookieService.get('tokenrefexp'); // refresh expiration
// refresh token -> access token -> original request
return of(Number(expirationTokenRefresh) < Date.now()).pipe(
mergeMap(expire => expire
? this.authService.refreshTokenRefresh()
: of(Number(expirationToken) < Date.now())
),
mergeMap(expire => expire
? this.authService.refreshToken()
: of(true)
),
mergeMap(ok => next.handle(req.clone({ withCredentials: true })))
);
}
}
// auth service
refreshToken() {
return this.http.get(`${BACKEND_URL}/refreshtoken`);
}
refreshTokenRefresh() {
return this.http.get(`${BACKEND_URL}/refreshtokenref`);
}
请务必同意@Xinan的观点,即拦截器有时可能会带来更多问题。创建自己的http服务可能更好
class HttpService{
constructoer(private _http:HttpClient)
preIntercept(url,options){
this._http.get(tokenUrl).pipe(
map(res=>{
//do your stuff
return {url,options}
}))
}
get(url,options={}){
return this.preIntercept(url,options).pipe(
mergeMap(({url,options})=>this._http.get(url,options))
}
}