React优惠券项目Redux+JWT登出清LocalStorage报401错误如何解决
401报错根因
- 登出请求使用了原生
axios,没有使用你封装的自动携带token的tokenAxios实例,请求头没有带上Authorization字段,后端鉴权不通过
- 登出请求使用了原生
- 你的token是存在localStorage的
user对象中,不是单独存的token字段,localStorage.getItem('token')根本拿不到有效值
- 你的token是存在localStorage的
- 登出组件的
useEffect为空,进入登出页面后没有自动触发登出逻辑
- 登出组件的
- 当前登出接口写死了
/customer/logout路径,不支持管理员、公司角色的登出请求
- 当前登出接口写死了
修复方案
1. 标准修复(需要服务端注销token场景)
替换登出请求的axios实例,适配多角色登出路径,修正逻辑执行时机,修改Logout组件代码如下:
// 引入你自己封装的tokenAxios import tokenAxios from '你存放tokenAxios的文件路径'; function Logout(): JSX.Element { const history = useHistory(); async function logout() { try { // 从Redux中拿到当前用户的角色,匹配对应的登出接口路径 const user = store.getState().authState.user; let logoutUrl = ''; // 这里的type换成你NewUserModel里存储用户角色的字段名 switch(user.type) { case 'Customer': logoutUrl = "http://localhost:8080/customer/logout"; break; case 'Company': logoutUrl = "http://localhost:8080/company/logout"; break; case 'Administrator': logoutUrl = "http://localhost:8080/admin/logout"; break; } // 用tokenAxios发起请求,自动携带token头 await tokenAxios.delete(logoutUrl); notify.success(SccMsg.LOGOUT_SUCCESS); } catch (err) { notify.error('登出请求失败,请重试'); } finally { // 不管接口调用成功失败,都清除本地状态,避免用户异常卡在登录态 store.dispatch(logoutAction()); history.push("/home"); } } // 进入页面立即执行登出逻辑 useEffect(() => { logout(); }, []); return <></>; }
可选优化:统一鉴权失败处理
可以在tokenAxios的响应拦截器里增加401状态码的统一处理,只要接口返回401就自动清空本地登录态跳转到登录页,避免异常情况用户卡在登录态:
tokenAxios.interceptors.response.use( response => response, error => { if (error.response?.status === 401) { store.dispatch(logoutAction()); window.location.href = '/login'; } return Promise.reject(error); } );
2. 简化方案(无服务端token注销需求场景)
如果你的后端JWT没有做主动黑名单校验,不需要服务端注销token的话,可以直接省略调用登出接口的步骤,直接清空本地存储和Redux状态即可完成登出,完全避免401问题:
function Logout(): JSX.Element { const history = useHistory(); useEffect(() => { store.dispatch(logoutAction()); notify.success(SccMsg.LOGOUT_SUCCESS); history.push("/home"); }, []); return <></>; }
内容的提问来源于stack exchange,提问作者Fastaca Girasol
相关产品推荐
相关产品推荐

