在 RxJS mergeMap 之间导航时如何避免多个 HttpInterceptor 调用? [英] How to avoid multiple HttpInterceptor calls while navigating between RxJS mergeMap?

查看:42
本文介绍了在 RxJS mergeMap 之间导航时如何避免多个 HttpInterceptor 调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用了两个 JWT 令牌 - 刷新令牌(7 天后过期)和访问令牌(15 分钟后过期).它们存储在 httpOnly cookie 中,可以通过服务器访问.刷新方法对新令牌进行签名并将其存储在 cookie 中.我需要在每次请求后检查这些令牌是否已过期:

I'm using two JWT tokens - Refresh Token(expires after 7 days) and Access Token (expires after 15 min). They are stored on httpOnly cookies and can be accessed via server. Refresh methods signs new token and store it on a cookie. I need to check if these tokens are expired after every request like this:

@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 的原始请求.总之,我可能需要在原始请求之前发送请求.

I may send one request to refresh a token, and then another request to refresh second token, and finally the original request with updated cookies. In summary, I may need to send requests before my original request.

问题是:每次发出请求时,都会有一个请求循环到AuthInterceptor.请求一和二(令牌)不应调用 AuthInterceptor.

Problem is: There is a loop of requests going to AuthInterceptor every time a request is made. Request one and two (tokens) shouldn't call AuthInterceptor.

推荐答案

如果请求 url 是为了令牌,则进行条件检查以跳过拦截器.

Do a conditional check to skip the interceptor if the request url is for token.

@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服务可能会更好

Do agree to @Xinan that interceptor can sometimes be more of a problem. Create your own http service might be better

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))
}

}

这篇关于在 RxJS mergeMap 之间导航时如何避免多个 HttpInterceptor 调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆