You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

刷新令牌实现遇401未授权错误,请求技术协助

实现Refresh Token时遇到401 Unauthorized错误求助

后端通过PostMan、curl调用均正常:携带refresh token请求头后,能成功返回可用的accessToken;但前端调用时触发401错误,请求协助排查。

拦截器代码

export const customInterceptor: HttpInterceptorFn = (req, next) => {
    const excludedRoutes = ['/login']; // 可自定义的路由数组
    const shouldExclude = excludedRoutes.some(route => req.url.includes(route));
    const authService = inject(AuthService);

    if (shouldExclude) {
        return next(req);
    }

    const token = authService.getAuthToken();
    const cloneRequest = req.clone({
        setHeaders: {
            Authorization: `Bearer ${token}`
        }
    });

    return next(cloneRequest).pipe(
        catchError((error) => {
            if (error.status === 401) {
                console.log("From the interceptor, here is the error: " + error.status);
                return authService.refreshToken().pipe(
                    switchMap((res) => {
                        localStorage.setItem('authToken', res.accessToken);
                        console.log("From the interceptor, the new authToken is: " + res.accessToken);
                        const newReq = req.clone({
                            setHeaders: {
                                Authorization: `Bearer ${res.accessToken}`
                            }
                        });

                        return next(newReq);
                    }),
                    catchError((refreshErr) => {
                        const finalError = new Error(refreshErr);
                        console.log("Error refreshing the token", finalError);
                        authService.logout();
                        return throwError(() => new Error('Session expired, please log in again'));
                    })
                );
            } else {
                // 处理其他错误(如网络错误)
                return throwError(() => error);
            }
        })
    );
};

服务方法代码

refreshToken() {
    const refreshToken = localStorage.getItem('refreshToken');
    console.log("The refreshToken inside the method is: " + refreshToken);

    if (!refreshToken) {
        throw new Error('Refresh token missing');
    }
    
    console.log("Sending refresh token to backend: " + refreshToken);
    
    return this._httpClient.post<any>(`${this.baseURL}/refresh`, {}, {
        headers: {
            Authorization: `Bearer ${refreshToken}`
        }
    }).pipe(
        catchError((error) => {
            console.error("Refresh token error:", error);
            return throwError(() => new Error("Refresh error"));
        })
    );
}

排查方向与解决建议

  • 拦截器范围问题:当前拦截器仅排除了/login,但/refresh请求会被自动带上过期的accessToken,导致后端优先校验无效的accessToken返回401。需将/refresh加入excludedRoutes数组,避免拦截器给该请求添加Authorization头。
  • 请求头格式校验:在浏览器Network面板查看实际发送的请求头,对比PostMan的请求头,确认Authorization: Bearer ${refreshToken}格式是否完全一致,检查token是否存在多余空格、转义字符。
  • 跨域配置问题:检查后端CORS配置是否允许前端携带Authorization请求头,若未配置会导致浏览器自动屏蔽该头,触发401。
  • Token存储校验:对比console.log输出的refreshToken值与PostMan中使用的token,确认存储和读取过程中是否存在篡改、编码错误。
  • 后端校验逻辑:复制浏览器中的请求为curl命令执行,排查是否存在后端对请求来源、User-Agent等额外校验导致的差异。

内容的提问来源于stack exchange,提问作者Gustavo Starace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 02:33:15