Angular HttpInterceptor 与 Github API 调用混淆

Posted

技术标签:

【中文标题】Angular HttpInterceptor 与 Github API 调用混淆【英文标题】:Angular HttpInterceptor Messing With Github API Call 【发布时间】:2019-10-01 00:14:22 【问题描述】:

我目前正在实现一个身份验证系统,其中用户登录并从服务器接收 JWT 令牌,该令牌存储在 localStorage 中。我还编写了一个自定义 HttpInterceptor,它将用户的令牌附加到传出的 HTTP 请求中。这适用于本地端点,但是我也有一个 GET 请求从 GitHub 的 API 获取每个用户的头像,并且由于拦截器,这不再有效。我从 GitHub 收到 401 身份验证错误。

这是来自 HttpInterceptor 的代码:

@Injectable()
export class AuthInterceptor implements HttpInterceptor 
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> 
    const idToken = localStorage.getItem("access_token");

    if (idToken && req.url.includes("localhost")) 
      const cloned = req.clone(
        headers: req.headers.set("Authorization", `Bearer $idToken`)
      );
      return next.handle(cloned);
     else 
      return next.handle(req);
    
  

以下是发送到 GitHub 的请求标头:

Accept: application/json, text/plain, */*
Authorization: token ... (removed for privacy)
Content-Type: application/json
Origin: http://localhost:4200
Referer: http://localhost:4200/contacts
User-Agent: ...(removed for privacy)

这是来自 GitHub API 的响应:

Request URL: https://api.github.com/users/...
Request Method: GET
Status Code: 401 Unauthorized
Remote Address: 192.30.253.117:443
Referrer Policy: no-referrer-when-downgrade

这是获取 GitHub 头像的服务中的代码:

const githubOptions = 
  headers: new HttpHeaders(
    "Content-Type": "application/json",
    Authorization: "token ..." // removed for privacy
  )
;

@Injectable(
  providedIn: "root"
)
export class ContactServiceService 
  constructor(private http: HttpClient) 

  ...

  getGithub(user: string): Promise<any> 
    return this.http
      .get<any>(`https://api.github.com/users/$user`, githubOptions)
      .toPromise();
  

奇怪的是,如果我在 Chrome 网络控制台中双击 HTTP 请求,它会正常运行并返回所需的响应。但无论出于何种原因,HttpInterceptor 都会阻止它在我的代码中通过。

非常感谢任何帮助!

【问题讨论】:

【参考方案1】:

这是因为您的应用程序的 Authorization 标头覆盖了 github 的标头。实际上,您正试图通过使用此 if 语句 if (idToken &amp;&amp; req.url.includes("localhost")) 来检查 url 来避免这种情况@

但是,您的 req.headers.set 调用似乎也覆盖了其他请求的 Authorization 标头。尝试像这样设置标题:

const cloned = request.clone(
  setHeaders: 
    Authorization: `Bearer $idToken`
  
);

【讨论】:

我试了一下,但还是一样,还是 401。还有其他想法吗? 奇怪的是,当我在 Chrome 网络控制台中查看传出的 HTTP 标头时,它确实显示了正确的令牌被发送到 GitHub,但它仍然给我一个 401。 嗯,确实很奇怪 :) 我认为您应该比较成功调用删除拦截器的请求标头和带有错误的请求标头。如果不是 Authorization 令牌值,那么我们现在想不到的其他东西应该会产生影响。 我刚刚重新启动了我的开发服务器,它现在似乎可以正常工作了。不知道发生了什么,但感谢您的帮助

以上是关于Angular HttpInterceptor 与 Github API 调用混淆的主要内容,如果未能解决你的问题,请参考以下文章

使用 HttpInterceptor 的 Angular 1.5 超时

从 Angular HttpInterceptor 调用 Promise

使用 Angular 4.3 的 HttpInterceptor 拦截 HTTP 响应标头

typescript Angular HttpInterceptor

从 Angular 中的 HttpInterceptor 访问 HTTP 错误响应正文

Angular 11:对 HttpInterceptor 进行单元测试 - 异步计时器或 AfterAll 错误