React路由保护失效问题:未登录仍可访问受保护路由
问题排查与修复方案
我帮你梳理了代码里的几个核心问题,正是这些问题导致你的ProtectedRoute没有起到拦截未登录用户的作用:
1. 最关键的错误:忘记调用isAuthenticated函数
你在两处地方都直接引用了isAuthenticated这个函数名,但没有调用它(加括号)。因为isAuthenticated是一个返回布尔值的函数,不是一个直接的布尔变量,所以必须调用它才能拿到当前的认证状态:
修改ProtectedRoute.js:
import React from "react"; import { Route, Redirect } from "react-router-dom"; import { isAuthenticated } from "./function"; export const ProtectedRoute = ({ component: Component, ...rest }) => { return ( <Route {...rest} render={ (props) => { // 这里要调用函数 isAuthenticated() if (isAuthenticated()) { return <Component {...props}/> } else { return <Redirect to={ { pathname: "/admin", state: { from: props.location } } }/> } } }/> ) }
修改登录组件的handleSubmit:
handleSubmit(e) { e.preventDefault(); const isValid = this.validate(); const user = { username: this.state.username, password: this.state.password } loginUser(user).then(res => { // 同样要调用函数 isAuthenticated() if (isAuthenticated()) { this.props.history.push('/men'); } }).catch(err => { // 可以在这里处理登录失败的提示,比如alert用户名或密码错误 console.log('登录失败:', err); }) }
2. 修复loginUser的Promise链问题
你的loginUser函数里,axios请求的then块没有返回响应结果,而且登录失败时没有重置authenticated状态,这会导致后续的Promise逻辑出现异常:
修改functions.js里的loginUser:
import axios from 'axios'; // 别忘了导入axios! let authenticated = false; export const loginUser = user => { return axios.post("/users/login", { username: user.username, password: user.password }) .then(res => { authenticated = true; return res; // 返回响应,让后续的then能拿到登录结果 }).catch(err => { authenticated = false; // 登录失败时重置认证状态 console.log(err); throw err; // 抛出错误,让调用方的catch可以捕获 }) } export const isAuthenticated = () => { return authenticated }
3. 可选但重要:添加状态持久化
目前你的authenticated变量只存在内存中,页面刷新后就会变回false,用户需要重新登录。如果想让登录状态在页面刷新后保持,可以把状态存在localStorage里:
更新functions.js:
import axios from 'axios'; // 初始化时从localStorage读取状态 let authenticated = localStorage.getItem('authenticated') === 'true'; export const loginUser = user => { return axios.post("/users/login", { username: user.username, password: user.password }) .then(res => { authenticated = true; localStorage.setItem('authenticated', 'true'); // 保存到localStorage return res; }).catch(err => { authenticated = false; localStorage.setItem('authenticated', 'false'); console.log(err); throw err; }) } export const isAuthenticated = () => { return authenticated; } // 可以新增一个登出函数 export const logoutUser = () => { authenticated = false; localStorage.setItem('authenticated', 'false'); }
4. 最后确认路由配置
确保你的App.js里,所有路由都被BrowserRouter(或Router)包裹,并且Switch组件正确包裹了所有路由:
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import { ProtectedRoute } from './protected.route'; import DashBoard from './DashBoard'; import Login from './Login'; // 你的登录组件 function App() { return ( <Router> <Switch> {/* 保护路由 */} <ProtectedRoute exact path="/dash" component={DashBoard}/> {/* 登录路由 */} <Route path="/admin" component={Login}/> {/* 其他公共路由 */} <Route path="/men" component={MenPage}/> </Switch> </Router> ); } export default App;
做完这些修改后,你的ProtectedRoute应该就能正常拦截未登录用户,跳转到登录页面了。
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

