Angular特定API无法添加JWT Token到请求头问题排查
Angular中特定API请求JWT Token无法添加到请求头的问题
仅在addToBookmark()接口请求中,JWT Token无法正确添加到请求头,返回401 Unauthorized错误;但getBookmarks()接口可正常工作。通过控制台日志观察到两个函数内的httpOptions.headers内容存在差异。
问题代码
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs'; import { environment } from 'src/environments/environment'; import { UserAuthService } from '../user-auth/user-auth.service'; import { Bookmark } from 'src/app/models/api/bookmarks/Bookmark'; let httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json', }), }; @Injectable({ providedIn: 'root', }) export class BookmarksService { jwtToken: string | null = this.userAuthService.getJwtToken(); private apiUrl: string = environment.apiUrl; constructor( private http: HttpClient, private userAuthService: UserAuthService ) {} // Get bookmarks getBookmarks(): Observable<Bookmark> { this.addJwtToHeaders(); const url: string = `${this.apiUrl}/bookmark/`; return this.http.get<Bookmark>(url, httpOptions); } addToBookmark(id: string): Observable<any> { this.addJwtToHeaders(); console.log(httpOptions.headers); const url: string = `${this.apiUrl}/bookmark_add/${id}/`; return this.http.post<any>(url, httpOptions); } addJwtToHeaders(): void { const auth = httpOptions.headers.get('Authorization'); if (!auth) { if (!this.jwtToken) return; httpOptions.headers = httpOptions.headers.append( 'Authorization', `Token ${this.jwtToken}` ); } } }
核心问题分析
- POST请求参数顺序错误:
http.post的第二个参数是请求体,第三个参数才是请求配置(包含headers)。你把httpOptions当成了请求体传入,导致请求头根本没被正确传递给POST请求。 - 全局
httpOptions状态污染:全局变量httpOptions会被多次调用修改,后续请求可能复用旧的配置,无法保证Token的实时有效性。 - Token初始化时机问题:类初始化时获取
jwtToken,此时userAuthService可能未完成初始化,导致Token获取失败。
修复方案
修改代码如下,解决上述所有问题:
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs'; import { environment } from 'src/environments/environment'; import { UserAuthService } from '../user-auth/user-auth.service'; import { Bookmark } from 'src/app/models/api/bookmarks/Bookmark'; @Injectable({ providedIn: 'root', }) export class BookmarksService { private apiUrl: string = environment.apiUrl; constructor( private http: HttpClient, private userAuthService: UserAuthService ) {} // Get bookmarks getBookmarks(): Observable<Bookmark> { const httpOptions = this.getHttpOptions(); const url: string = `${this.apiUrl}/bookmark/`; return this.http.get<Bookmark>(url, httpOptions); } addToBookmark(id: string): Observable<any> { const httpOptions = this.getHttpOptions(); console.log(httpOptions.headers); const url: string = `${this.apiUrl}/bookmark_add/${id}/`; // 第二个参数传请求体(无内容则传空对象),第三个参数传请求配置 return this.http.post<any>(url, {}, httpOptions); } // 每次请求创建独立的请求头配置,实时获取最新Token private getHttpOptions(): { headers: HttpHeaders } { let headers = new HttpHeaders({ 'Content-Type': 'application/json', }); const jwtToken = this.userAuthService.getJwtToken(); if (jwtToken) { headers = headers.append('Authorization', `Token ${jwtToken}`); } return { headers }; } }
修复说明
- 移除全局
httpOptions,每次请求通过getHttpOptions()创建独立的配置对象,避免状态污染。 - 在
getHttpOptions()中实时获取最新Token,确保每次请求使用的都是有效Token。 - 修正POST请求的参数顺序,将请求体(空对象)作为第二个参数,请求配置作为第三个参数,保证请求头被正确携带。
内容的提问来源于stack exchange,提问作者devZ
相关产品推荐
相关产品推荐

