Angular 5不同账号SSO登录不更新token,返回旧数据求助
问题分析与解决方案
核心问题根源
你遇到的这个问题,主要有两个关键原因:
GET请求的浏览器缓存
你的verifyCharacter方法用的是GET请求,浏览器默认会对相同URL的GET请求进行缓存。即使你更换了新的token并更新了请求头,有些浏览器(或者后端服务器的缓存配置)会忽略请求头的变化,直接返回之前缓存的旧账号数据。只有当缓存过期(比如token刷新时),浏览器才会发起新的请求,返回正确的新账号数据。服务状态依赖的隐患
你的AuthWithEveService是Angular的单例服务,里面的activeToken和activeAuthHeader是全局共享的状态。虽然在组件里你先调用initializeMemberValues更新状态,再调用verifyCharacter,但这种依赖全局状态的设计很容易出现状态不一致的问题——比如如果有其他组件同时调用这个服务,可能会覆盖掉你刚设置的token。更关键的是,verifyCharacter方法明明接收了token参数,却完全没用到,这不仅浪费参数,还让代码逻辑更混乱。
具体修复步骤
1. 修复AuthWithEveService的verifyCharacter方法
让方法直接使用传入的token生成请求头,同时禁用浏览器缓存:
@Injectable() export class AuthWithEveService { // 移除不必要的全局状态变量:activeToken、activeAuthHeader constructor(private http: HttpClient) {} verifyCharacter(token: string): Observable<Object> { // 直接用传入的token生成请求头,不依赖全局状态 const authHeader = new HttpHeaders({ 'Authorization': `Bearer ${token}`, // 添加缓存控制头,强制浏览器不缓存 'Cache-Control': 'no-cache', 'Pragma': 'no-cache', 'Expires': '0' }); return this.http.get(verifyGETUrl, { headers: authHeader }); } SSOUrl(): string { let scope = '&scope='+scopes[0]; return authorize_url + response_type + redirect_uri + client_id + scope; } // 如果其他地方不需要用到这个方法,可以直接移除 // initializeMemberValues(token: string) { // this.activeToken = token; // this.activeAuthHeader = new HttpHeaders({ // 'Authorization': 'Bearer '+token // }); // } }
2. 简化AuthComponent的登录逻辑
既然verifyCharacter现在直接用传入的token,就不需要再调用initializeMemberValues了:
export class UserHasAuthenticatedComponent implements OnInit { constructor( private route: ActivatedRoute, private router: Router, private authService: AuthWithEveService, private apiService: APIAccessService, private data: FirebaseDataService, private http: HttpClient ) { } ngOnInit() { let access_token = this.route.snapshot.fragment.slice(13, 100); // 移除这一行,因为verifyCharacter现在直接使用传入的token // this.authService.initializeMemberValues(access_token); this.authService.verifyCharacter(access_token).subscribe( (obj: CharacterData) => { this.apiService.AuthedCharacter = obj; let charName = obj.CharacterName; this.data.adminDoc.ref.get().then(doc => { if(doc.data().adminCharacterNames.includes(charName)){ this.router.navigate(['/admin']); } else{ this.router.navigate(['/auth/success']); } }); }); } }
额外说明
如果禁用缓存的请求头不起作用,你还可以通过给GET请求添加一个随机参数的方式绕过缓存,比如:
return this.http.get(verifyGETUrl, { headers: authHeader, params: new HttpParams().set('t', Date.now().toString()) });
这个随机参数t每次请求都不一样,浏览器会认为是不同的URL,从而不会返回缓存的旧数据。
内容的提问来源于stack exchange,提问作者BenjaminApprill
相关产品推荐
相关产品推荐

