ABP商业版多标签页持续刷新及自动登出问题求助
解决ABP商业版多标签页无限刷新及access token过期登出问题
一、搞定多标签页令牌冲突引发的无限刷新
浏览器LocalStorage为所有标签页共享,多个标签页同时刷新令牌时会互相覆盖,进而触发无限循环。可以从两方面处理:
- 监听LocalStorage同步令牌
直接在app.component.ts中添加LocalStorage监听,当其他标签页更新令牌时,当前标签页同步更新本地令牌,避免重复发起刷新请求:
ngOnInit() { window.addEventListener('storage', (event) => { // 替换为你的OIDC存储键,格式一般为oidc.user:<授权地址>:<客户端ID> if (event.key === 'oidc.user:https://your-auth-server.com:your-client-id') { const newTokenData = JSON.parse(event.newValue || '{}'); this.oidcSecurityService.setAuthorizationData(newTokenData); } }); }
- 给令牌刷新加并发锁
ABP默认的OAuth拦截器未处理并发刷新场景,自定义拦截器添加锁机制,确保同一时间仅一个标签页发起刷新请求:
// 自定义OAuth拦截器 @Injectable() export class CustomOAuthInterceptor extends OAuthInterceptor { private isRefreshing = false; private refreshSubject = new Subject<any>(); intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { if (this.oauthService.hasValidAccessToken()) { return next.handle(this.addAccessToken(req)); } else if (!this.isRefreshing) { this.isRefreshing = true; this.refreshSubject.next(null); return this.oauthService.refreshToken().pipe( switchMap((token) => { this.isRefreshing = false; this.refreshSubject.next(token); return next.handle(this.addAccessToken(req)); }), catchError((err) => { this.isRefreshing = false; this.refreshSubject.error(err); return this.handleError(err, req, next); }) ); } else { return this.refreshSubject.pipe( filter(token => token !== null), take(1), switchMap(token => next.handle(this.addAccessToken(req))) ); } } }
随后在app.module.ts中替换默认拦截器:
providers: [ { provide: OAuthInterceptor, useClass: CustomOAuthInterceptor } ]
二、调整登出逻辑:仅在refresh token过期时登出
ABP默认在access token过期且刷新失败时直接登出,我们需要区分失败原因,仅在refresh token过期时触发登出:
- 自定义OIDC失败事件处理
在app.component.ts中监听刷新失败事件,根据错误类型判断是否登出:
ngOnInit() { this.oidcSecurityService.refreshTokenFailed$.subscribe((err) => { // 识别refresh token过期的错误特征 if (err.error === 'invalid_grant' || err.error_description?.includes('refresh token')) { // 仅refresh token过期时执行登出 this.oidcSecurityService.logoff(); } else { // 其他错误场景重新发起授权 this.oidcSecurityService.authorize(); } }); }
- 优化令牌过期配置
在environment.ts中调整OIDC参数,减少刷新频率,降低多标签页冲突概率:
export const environment = { // ...其他配置 oAuthConfig: { issuer: 'https://your-auth-server.com', clientId: 'your-client-id', accessTokenExpiringNotificationTime: 60, // 提前60秒通知access token过期 refreshTokenRenewInSeconds: 300, // 提前5分钟刷新refresh token silentRenew: false, // 关闭静默刷新,避免多标签页冲突 // ...其他配置 } };
三、验证默认项目配置
如果默认ABP项目就出现该问题,检查是否开启了silentRenew,开启的话直接关闭,改用上述手动刷新逻辑,可有效减少多标签页冲突。
内容的提问来源于stack exchange,提问作者Jalaleddin Hosseini
相关产品推荐
相关产品推荐

