ReactJS用户登出后点击浏览器返回按钮仍可访问仪表盘如何解决
问题根因
- 私有路由ConfigRoute只判断了加载状态,没有校验用户登录状态,加载完成后不管用户有没有登录都会直接渲染受保护组件
- 登出逻辑只清理了本地存储,没有主动跳转到登录页,浏览器历史栈还保留了仪表盘页面的访问记录
- checkLoginAction仅处理了登录态有效时跳转到仪表盘的逻辑,没有处理登录态失效时跳转到登录页的分支
- 未配置页面缓存规则,浏览器可能直接读取缓存的历史页面,不触发路由校验
修复步骤
1. 补全checkLoginAction的未登录分支逻辑
export const checkLoginAction = history => dispatch => { //! Loading dispatchLoading(dispatch, CHECK_LOGIN_ACTION); const user = JSON.parse(window.localStorage.getItem('user')); if (user) { firebase .database() .ref(`users/${user.uid}`) .once('value') .then(snapshot => { if (snapshot.val()) { window.localStorage.setItem('user', JSON.stringify(snapshot.val())); dispatchSuccess(dispatch, CHECK_LOGIN_ACTION, snapshot.val()); } else { // 用户不存在,清空存储跳登录 window.localStorage.removeItem('user'); dispatchSuccess(dispatch, CHECK_LOGIN_ACTION, null); history.replace('/auth/login'); } }) .catch(() => { // 请求失败,清空存储跳登录 window.localStorage.removeItem('user'); dispatchSuccess(dispatch, CHECK_LOGIN_ACTION, null); history.replace('/auth/login'); }) } else { // 本地无用户信息,直接跳登录 dispatchSuccess(dispatch, CHECK_LOGIN_ACTION, null); history.replace('/auth/login'); } };
2. 补全私有路由的登录拦截逻辑
function ConfigRoute({ component: Component, dispatch, checkLoginLoading, checkLoginResult, ...rest }) { const history = useHistory(); useEffect(() => { dispatch(checkLoginAction(history)); }, [dispatch, history]); return ( <Route {...rest} render={(props) => { if (checkLoginLoading) { return <LoadingIndicator /> } // 校验登录结果,未登录直接重定向到登录页 else if (checkLoginResult) { return <Component {...props} /> } else { return <Redirect to="/auth/login" /> } }} /> ); };
3. 登出完成后跳转登录页并替换历史栈
调用logoutUserAction时传入当前history实例即可:
export const logoutUserAction = (history) => dispatch => { //! Loading dispatchLoading(dispatch, LOGOUT_USER_ACTION); firebase .auth() .signOut() .then(() => { window.localStorage.removeItem('user'); dispatchSuccess(dispatch, LOGOUT_USER_ACTION, 'Success Logout!!!'); // 替换当前历史记录为登录页,避免返回键回到受保护页面 history.replace('/auth/login'); }) .catch(() => { window.localStorage.removeItem('user'); dispatchError(dispatch, LOGOUT_USER_ACTION, 'Failed Logout!!!'); // 登出失败也要跳登录 history.replace('/auth/login'); }); };
4. 禁用受保护页面的缓存
在项目public/index.html的head标签中添加以下meta标签,防止浏览器直接读取缓存的历史页面:
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="0" />
内容的提问来源于stack exchange,提问作者Miraii App
相关产品推荐
相关产品推荐

