为何传入SignalR accessTokenFactory的Observable仅会执行一次
问题根源
- 调用
connect方法时你已经执行了getAccessToken(),传入的是单次请求生成的Observable对象,该对象仅会在首次订阅时触发MSAL取令牌逻辑,后续复用不会产生新的令牌请求。 connect方法内提前创建了固定的token$流,accessTokenFactory每次执行都复用该流转Promise的结果,RxJS 中单播Observable转Promise后只会返回首次订阅的缓存值,不会重新执行上游取令牌逻辑。
解决方案
调整逻辑为每次SignalR需要令牌时,都重新触发getAccessToken()调用:
步骤1:调整connect方法的入参类型和内部实现
将入参从已生成的Observable改为返回Observable的工厂函数,每次令牌工厂被调用时才生成新的取令牌流:
import { firstValueFrom } from 'rxjs'; // RxJS 7+ 需引入,低版本可省略使用toPromise connect(accessTokenProvider: () => Observable<any>): Promise<any> { const options: IHttpConnectionOptions = { accessTokenFactory: async () => { // 每次调用都重新执行取令牌逻辑,自动处理令牌刷新 const authResult = await firstValueFrom(accessTokenProvider()); return authResult.accessToken; // RxJS 6及以下版本可使用原有toPromise写法: // return accessTokenProvider().pipe(map(res => res.accessToken)).toPromise(); } }; this.connection = new HubConnectionBuilder() .withUrl(this.hubUrl, options) // 其余原有逻辑保持不变 }
步骤2:调整connect方法的调用方式
不要直接执行getAccessToken传入结果,改为传入箭头函数包裹调用逻辑:
this._realTimeNotificationService.connect(() => this._authService.getAccessToken(environment.backendUrl));
修改完成后,SignalR首次建连、自动重连时都会重新执行令牌工厂逻辑,MSAL的acquireTokenSilent会自动判断当前令牌有效性,过期时自动用刷新令牌换取新的有效令牌,即可解决重连时使用过期令牌的问题。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

