You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 23:53:15