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

React登录后禁止访问登录页与首页的权限控制问题

解决方案

你的核心问题是登录状态更新与路由跳转的顺序错误,导致登录后公共路由的拦截逻辑未能及时生效。另外,调整部分组件逻辑可让状态与路由行为更一致。

问题分析

  1. Login组件中,表单提交时先执行路由跳转再更新认证状态,跳转瞬间isUserAuthenticated仍为false,导致PublicRoutes无法触发拦截。
  2. Header的Logout按钮先跳转首页再更新状态,逻辑顺序不合理,可能引发不必要的路由渲染。

修改步骤

1. 修复Login组件提交逻辑

将认证状态更新放在表单提交逻辑中,确保状态更新完成后再执行跳转:

// Login.jsx
import React from 'react'
import { useState } from 'react'
import { Container, Row, Col, Card, Form } from 'react-bootstrap'
import { Navigate, useLocation, useNavigate } from 'react-router-dom'

const Login = ({ isUserAuthenticated, userAuth }) => {
  const [username, setUsername] = useState("")
  const [password, setPassword] = useState("")
  const [umessage, setUM] = useState("Your username must be: Admin")
  const [pmessage, setPM] = useState("Your password must be: Admin")
  const location = useLocation()
  const navigate = useNavigate()
  const from = location.state?.from?.pathname || "/dashboard"
  
  const changeUsername = (e) => {
    setUsername(e.target.value)
    if (e.target.value === "Admin") setUM("Perfect")
  }

  const changePassword = (e) => {
    setPassword(e.target.value)
    if (e.target.value === "Admin") setPM("Perfect")
  }

  const enableButton = () => {
    return !(username === "Admin" && password === "Admin")
  }

  return isUserAuthenticated ? (
    <Navigate to="/dashboard" replace />
  ) : (
    <Container className='mt-5'>
      <Row>
        <Col md="3"></Col>
        <Col md="6">
          <Card>
            <Card.Header className='p-3' style={{ textAlign: 'center' }}>
              <h4>LOGIN HERE</h4>
            </Card.Header>
            <Card.Body>
              <Form onSubmit={(e) => {
                e.preventDefault()
                // 先更新认证状态,再执行跳转
                userAuth()
                navigate(from, { replace: true })
              }}>
                <Form.Group className="mb-3">
                  <Form.Control
                    className="mb-2"
                    type="text"
                    required
                    onChange={changeUsername}
                    value={username}
                    placeholder="Enter your username here"
                  />
                  <Form.Text>{umessage}</Form.Text>
                  <Form.Control
                    className="mb-2"
                    type="password"
                    required
                    onChange={changePassword}
                    value={password}
                    placeholder="Enter your password"
                  />
                  <Form.Text>{pmessage}</Form.Text>
                  <Form.Control
                    className='btn btn-block btn-primary mb-3'
                    disabled={enableButton()}
                    type='submit'
                    value="Login"
                  />
                </Form.Group>
              </Form>
            </Card.Body>
          </Card>
        </Col>
        <Col md="3"></Col>
      </Row>
    </Container>
  )
}

export default Login

2. 优化PublicRoutes组件(简化写法)

// PublicRoutes.js
import { Navigate, Outlet, useLocation } from 'react-router-dom'
import React from 'react'

const PublicRoutes = ({ isUserAuthenticated }) => {
  const location = useLocation()
  
  return isUserAuthenticated ? (
    <Navigate to="/dashboard" state={{ from: location }} replace />
  ) : (
    <Outlet />
  )
}

export default PublicRoutes

3. 调整Header的Logout逻辑

先更新认证状态再跳转,避免无效路由渲染:

// Header.jsx
import React from 'react'
import { Container, Navbar, Nav } from 'react-bootstrap'
import { Link, useNavigate } from 'react-router-dom'

function Header({ loggedIn, userAuth }) {
  const navigate = useNavigate()
  
  const handleLogout = () => {
    userAuth()
    navigate('/', { replace: true })
  }

  return (
    <Navbar bg='dark' expand='lg' variant="dark">
      <Container>
        <Link className='navbar-brand' to='/'>Server Tools</Link>
        <Navbar.Toggle aria-controls="basic-navbar-nav" />
        <Navbar.Collapse id="basic-navbar-nav" className="justify-content-end">
          <Nav className="ml-auto">
            {loggedIn ? (
              <>
                <Link className='nav-link' to='/dashboard'>Dashboard</Link>
                <button className='btn btn-success' onClick={handleLogout}>LOGOUT</button>
              </>
            ) : (
              <Link className='btn btn-success' to='/login'>LOGIN</Link>
            )}
          </Nav>
        </Navbar.Collapse>
      </Container>
    </Navbar>
  )
}

export default Header

验证效果

修改完成后:

  • 登录成功后,手动输入/或/login会自动跳转到/dashboard
  • 未登录时无法访问/dashboard,会被重定向到登录页
  • 登出后自动回到首页,且无法访问受保护路由

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:25:00