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

ReactJS中阻止用户手动修改浏览器URL进行路由访问

解决React路由中用户篡改LocalStorage角色访问管理员路由的问题

核心思路

前端不能完全信任客户端存储(比如localStorage)的权限信息,必须结合后端接口实时验证用户真实权限,同时优化权限校验逻辑的安全性和用户体验。

具体实现方案

1. 改造AdminAuth组件,加入后端权限验证

修改权限校验逻辑,不再仅依赖localStorage,而是调用后端接口确认用户的真实角色:

import React, { useState, useEffect } from "react";
import { Navigate } from "react-router-dom";
import { isAutheticated } from "../auth";
import { checkAdminPermission } from "../api/auth"; // 后端提供的权限验证接口

export const AdminAuth = ({ children, redirectTo }) => {
  const [isLoading, setIsLoading] = useState(true);
  const [isValidAdmin, setIsValidAdmin] = useState(false);
  const [errorMsg, setErrorMsg] = useState("");

  useEffect(() => {
    const verifyAdminPermission = async () => {
      try {
        const authData = isAutheticated();
        // 无基础认证信息直接判定无权限
        if (!authData?.token) {
          setErrorMsg("请先登录");
          setIsValidAdmin(false);
          return;
        }

        // 调用后端接口验证用户真实角色
        const response = await checkAdminPermission(authData.token);
        if (response.data.isAdmin) {
          setIsValidAdmin(true);
        } else {
          setErrorMsg("无管理员访问权限");
          setIsValidAdmin(false);
        }
      } catch (err) {
        setErrorMsg("权限验证失败,请重新登录");
        setIsValidAdmin(false);
      } finally {
        setIsLoading(false);
      }
    };

    verifyAdminPermission();
  }, []);

  // 加载状态显示过渡提示,避免页面闪烁
  if (isLoading) {
    return <div>权限验证中...</div>;
  }

  // 验证不通过时提示错误并跳转
  if (!isValidAdmin) {
    alert(errorMsg); // 也可替换为项目内的自定义错误提示组件
    return <Navigate to={redirectTo} replace />;
  }

  return children;
};

2. 使用HTTP-only Cookie存储会话信息

将用户的会话Token存入HTTP-only Cookie,而非localStorage。这种Cookie无法被客户端JavaScript读取或修改,能从根源上避免用户篡改会话相关信息,后端接口直接从Cookie中获取Token进行权限校验。

3. 统一管理员路由的权限隔离

把所有管理员专属路由统一嵌套在一个路由组下,批量应用AdminAuth组件,减少重复配置:

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
  },
  {
    path: "/main",
    element: (
      <AdminAuth redirectTo="/profile">
        <Main />
      </AdminAuth>
    ),
    // 管理员子路由自动继承父级权限校验
    children: [
      { path: "/main/dashboard", element: <Dashboard /> },
      { path: "/main/settings", element: <Settings /> },
    ],
  },
]);

4. 全局监听路由变化,二次校验

在App组件中监听路由变化,对管理员路由进行二次验证,防止用户直接修改URL跳转:

import { useLocation, useNavigate } from "react-router-dom";

function App() {
  const location = useLocation();
  const navigate = useNavigate();

  useEffect(() => {
    // 检测到访问管理员路由时触发校验
    if (location.pathname.startsWith("/main")) {
      const authData = isAutheticated();
      if (!authData?.token) {
        alert("请先登录");
        navigate("/profile", { replace: true });
      }
      // 可再次调用后端验证接口强化校验
    }
  }, [location, navigate]);

  return (
    // 你的App组件内容
  );
}

关键注意事项

  • 前端权限校验仅作为用户体验优化手段,核心权限控制必须依赖后端,所有敏感接口都要在后端层面校验用户权限。
  • 永远不要信任客户端传递的任何权限信息,必须通过后端接口确认用户的真实身份与权限。
  • 避免将敏感权限信息(如角色)暴露在客户端可修改的存储中,尽量通过后端接口实时获取。

内容的提问来源于stack exchange,提问作者user21103751

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 05:10:23