如何在不中断SignalR连接的情况下更换JWT Token?
无需断开SignalR连接即可更新过期Token的方法
是的,完全不需要断开重连就能更新Token。核心原因是你配置的accessTokenFactory是一个回调函数——SignalR不会只在连接初始化时获取一次Token,而是会在每次需要认证操作(比如发送Hub方法调用、心跳检测、自动重连)时重新调用这个工厂函数,获取最新的Token值。
基础实现示例
把固定的Token值改成可动态更新的变量,让工厂函数返回这个变量即可:
// 维护一个可随时更新的Token变量 let currentToken = "MyInitialToken"; const connection = new HubConnectionBuilder() .withUrl("/MyServer", { // 每次需要Token时都会调用这个函数 accessTokenFactory: () => currentToken }) .configureLogging(LogLevel.Information) .build(); connection.serverTimeoutInMilliseconds = 300000; connection.start(); // 当Token过期时,直接更新这个变量即可 function refreshToken(newToken: string) { currentToken = newToken; }
异步刷新Token场景
如果你的Token刷新需要调用异步API(比如从后端获取新Token),accessTokenFactory也支持返回Promise,示例如下:
let currentToken = "MyInitialToken"; const connection = new HubConnectionBuilder() .withUrl("/MyServer", { accessTokenFactory: async () => { // 先检查当前Token是否过期 if (isTokenExpired(currentToken)) { // 异步请求新Token currentToken = await fetch("/api/refresh-token").then(res => res.text()); } return currentToken; } }) .configureLogging(LogLevel.Information) .build(); // 辅助函数:判断Token是否过期(以JWT为例) function isTokenExpired(token: string): boolean { const payload = JSON.parse(atob(token.split('.')[1])); return payload.exp * 1000 < Date.now(); }
注意事项
- 确保
accessTokenFactory的逻辑是线程安全的,避免并发请求时出现Token不一致的问题(比如可以加简单的锁逻辑)。 - 若使用WebSocket传输,WebSocket握手时用的是初始化Token,但后续消息通过已建立的连接发送无需重新认证;一旦连接断开自动重连,会调用
accessTokenFactory获取新Token。若使用长轮询/Server-Sent Events传输,每次请求都会调用工厂函数取最新Token。
内容的提问来源于stack exchange,提问作者Jang-Ho Bae
相关产品推荐
相关产品推荐

