基于Django+React-Redux的Token认证校验功能异常排查
嘿,我帮你排查了下代码里的问题,核心是这几个地方导致Token校验后没有派发后续动作:
1. Token参数根本没传到校验动作里
你在Login组件的useEffect里明明拿到了localStorage里的Token,但调用props.authTokenCheck()的时候完全没把token传进去!而你的authTokenCheck action creator是明确需要接收token参数的:
export const authTokenCheck = (token:string) => (dispatch:any) => { ... }
这就导致Axios请求里的Authorization头是Token undefined,请求要么直接失败但没被正确捕获,要么后端直接返回401,而你的代码逻辑因为没拿到token根本没法正常走下去。
修复代码:
先改Login组件的useEffect:
useEffect(()=>{ const token = localStorage.getItem('Token'); if(token !== null) { props.authTokenCheck(token); // 必须把拿到的token传进去! } }, []) // 这里把依赖项改成空数组,只在组件挂载时校验一次;如果需要监听Token变化,再调整依赖
然后同步修改mapDispatchToProps里的映射:
const mapDispatchToProps = (dispatch:any) => { return { authLogin: (email:string,password:string) => dispatch(authLogin(email,password)), authTokenCheck: (token:string) => dispatch(authTokenCheck(token)), // 这里要接收token参数再派发 } };
2. 校验Token用错了API端点
你的authTokenCheck动作里用了authSignupAPI作为请求地址——这明显是注册接口吧?验证Token有效性应该调用一个专门用来返回当前用户信息的接口,比如DRF自带的/api/user/或者你自定义的校验端点,这样后端才能通过Authorization头里的Token返回对应用户,以此确认Token有效。如果用注册接口,要么返回错误,要么逻辑完全不对,自然没法触发success动作。
修复建议:
把请求地址换成你的Token验证接口,比如:
Axios.get('/api/auth/current-user/', { headers:{ Authorization: `Token ${token}` } })
3. useEffect依赖项的坑
你原来的依赖项是[localStorage.getItem('Token')],但localStorage.getItem()每次调用都会返回一个新的字符串引用,会导致useEffect无限触发。建议先改成空数组,只在组件挂载时执行一次Token校验;如果确实需要监听localStorage里Token的变化,可以添加一个storage事件监听:
useEffect(()=>{ const checkToken = () => { const token = localStorage.getItem('Token'); if(token !== null) { props.authTokenCheck(token); } }; // 组件挂载时校验一次 checkToken(); // 监听localStorage变化 window.addEventListener('storage', checkToken); return () => window.removeEventListener('storage', checkToken); }, [props.authTokenCheck])
可选:完善错误处理方便调试
在authTokenCheck的catch块里,可以把具体的错误信息传递给authFail,这样你能在Redux状态里看到为什么校验失败:
// 先修改authFail的定义 export const authFail = (type:string, errorMsg?:string) => { return { type: type, payload: { loading: false, isAuthenticated: false, token: null, user: null, error: errorMsg || 'Token验证失败' } } }; // 然后修改catch逻辑 .catch((error)=>{ localStorage.removeItem('Token'); const errMsg = error.response?.data?.detail || 'Token无效或已过期'; dispatch(authFail(actionTypes.AUTH_TOKEN_CHECK_FAIL, errMsg)); })
验证步骤
- 修复完上述代码后,先登录成功,确认localStorage里有Token
- 刷新页面,打开浏览器控制台的Network标签,看是否有请求发送到你的Token验证接口
- 打开Redux DevTools,确认
AUTH_TOKEN_CHECK_START之后,是否有AUTH_TOKEN_CHECK_SUCCESS或者AUTH_TOKEN_CHECK_FAIL动作被派发
这样应该就能解决你遇到的Token校验后无后续动作的问题了!
内容的提问来源于stack exchange,提问作者Khan Asfi Reza

