如何将Redux Store中的JWT传入Middleware以建立Socket.io连接
核心问题
你当前的代码里,中间件初始化时就一次性读取了state.auth.token,但这时候Auth0大概率还没完成登录流程,token是null。之后Redux状态里的token更新了,但中间件里的token变量不会自动同步,所以触发连接时传的还是初始的null,后端自然拿不到值。
另外你写的tokenPromise完全起不到监听token变化的作用——它只会在初始化时检查一次token,有就resolve,没有就一直pending,根本不会响应后续的state更新。
解决步骤
实时获取最新token
不要在中间件初始化时存token,而是在触发startConnecting动作时,直接从store.getState()里读取最新的token值:const notificationMiddleware: Middleware = store => { let socket: Socket; return next => action => { const isConnectionEsablished = socket && store.getState().notification.isConnected; // 实时获取最新的token const currentToken = store.getState().auth.token; if(notificationActions.startConnecting.match(action) && !isConnectionEsablished && currentToken !== null){ socket = io(process.env.REACT_APP_SERVER_URL, { withCredentials: true, auth: {token: currentToken } }); store.dispatch(notificationActions.connectionEstablished()); console.warn('WebSockets connect'); // 后续的socket事件监听代码保持不变... } next(action); } }关于useSelector的疑问
useSelector是React Hook,只能在函数组件或自定义Hook中使用,Redux中间件是普通函数,没法用它,直接从store.getState()取最新状态是正确的做法。是否需要用auth回调函数
Socket.io的auth配置确实支持异步回调(可以返回Promise),如果你的token需要通过异步方式获取(比如直接调用Auth0的SDK接口拿token,而不是从Redux state取),可以这么写:socket = io(process.env.REACT_APP_SERVER_URL, { withCredentials: true, auth: async (cb) => { // 这里写异步获取token的逻辑,比如调用Auth0的getTokenSilently() const token = await getTokenSilently(); cb({ token: token }); } });但如果你的token已经存在Redux state里,直接实时读取就足够,不需要额外用回调。
额外提示
后端当前的验证逻辑是硬编码判断token === 'token-pass',实际生产环境要换成真实的JWT验证逻辑,比如用jsonwebtoken库解析并验证token的有效性。
内容的提问来源于stack exchange,提问作者RJA

