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

React集成react-google-login SSO时如何配置仅登录可访问的私有路由

React Google SSO 私有路由实现修复方案

现有代码核心问题点:

  • 使用的react-router-dom v6版本不兼容旧版v5的路由render写法,原有PrivateRoute组件无法生效
  • AuthContext的包裹范围未覆盖侧边栏区域,侧边栏无法获取登录状态
  • 登录/登出逻辑中状态更新顺序错误,先读取localStorage再赋值,导致状态更新滞后
  • 登录路由被包裹在私有路由内,未登录用户无法正常访问登录页
  • 登录状态未做持久化初始化,页面刷新后登录状态丢失

对应文件修改代码

1. App.js 调整

import {useState} from 'react'
import {BrowserRouter, Routes, Route} from 'react-router-dom'
// 其他组件、样式导入省略

function App() {
  const [value,setValue] = useState()
  // 初始化从localStorage读取登录状态,转布尔值避免字符串判断错误
  const [loggedIn, setLoggedIn] = useState(() => {
    return localStorage.getItem('isLoggedIn') === 'true'
  })

  return (
    <>
    <Column style={{ width: "100%" }}>
      <Row horizontal="start" style={{ backgroundColor: "#0C5494" }}>
        <a href="/">
        <img alt="logo" className="photo" src={logo}/>
        </a> 
        </Row>
      {/* 把Context提到最外层,覆盖所有路由相关组件 */}
      <AuthContext.Provider value={{loggedIn,setLoggedIn}}>
      <TableCountContext.Provider value={{value,setValue}}>
      <BrowserRouter>
      <Row >
      <Column flexGrow={1}>
        {/* 私有路由包裹侧边栏,未登录不显示 */}
        <PrivateRoute>
          <Sidebar/>
        </PrivateRoute>
      </Column>
      <Column
          vertical="start"
          flexGrow={100}
        >
        <div className="mainContent">
          <Routes>
            {/* 公开路由:不需要登录即可访问 */}
            <Route path="/login" element={<Login/>}></Route>
            {/* 私有路由:需要登录才能访问 */}
            <Route path="/" element={
              <PrivateRoute>
                <RealHome/>
              </PrivateRoute>
            }></Route>
            <Route path="/search" element={
              <PrivateRoute>
                <Home/>
              </PrivateRoute>
            }></Route>
            <Route path="/FAQ" element={
              <PrivateRoute>
                <Faq/>
              </PrivateRoute>
            }></Route>
            <Route path="/Search-sec" element={
              <PrivateRoute>
                <SearchSec/>
              </PrivateRoute>
            }></Route>
          </Routes>
        </div>
      </Column>
      </Row>
      </BrowserRouter>
      </TableCountContext.Provider>
      </AuthContext.Provider>
      </Column>
    </>
  )
}

export default App

2. GoogleLoginButton.js 调整登录/登出逻辑

export default function GoogleLoginButton() {
    const clientId = "myGoogleID.apps.googleusercontent.com"
    // 初始化按钮显示状态和本地存储同步
    const [showLoginButton, setShowLoginButton] = useState(() => {
      return localStorage.getItem('isLoggedIn') !== 'true'
    })
    const [showLogoutButton, setShowLogoutButton] = useState(() => {
      return localStorage.getItem('isLoggedIn') === 'true'
    })
    const {loggedIn,setLoggedIn} = useContext(AuthContext)
    let navigate = useNavigate()
    const onLoginSuccess = (res) =>{
        console.log("Login Success:", res.profileObj);
        // 先更新本地存储,再更新全局状态
        localStorage.setItem('isLoggedIn', true);
        setLoggedIn(true)
        setShowLoginButton(false)
        setShowLogoutButton(true)
        navigate(`/`)
    }
    const onLoginFailure = (res)=>{
        console.log("Login Failed:", res)
    }

    const onSignoutSuccess = () =>{
        alert("You have been signed out successfully.")
        // 先更新本地存储,再更新全局状态
        localStorage.setItem('isLoggedIn', false);
        setLoggedIn(false)
        setShowLoginButton(true)
        setShowLogoutButton(false)
        navigate('/login')
    }
  
    
    return (
        <div>
            {showLoginButton ?
            <GoogleLogin
                clientId={clientId}
                buttonText="Login"
                onSuccess={onLoginSuccess}
                onFailure={onLoginFailure}
                cookiePolicy={"single_host_origin"}
                isSignedIn={true}
            /> : null }
            {showLogoutButton ?
            <GoogleLogout
                clientId={clientId}
                buttonText="Sign Out"
                onLogoutSuccess={onSignoutSuccess}
            /> : null}
            
        </div>
    )
}

3. PrivateRoute.js 适配react-router-dom v6重写

import React, {useContext} from "react"
import {Navigate} from "react-router-dom"
import { AuthContext } from "./Contexts"

export default function PrivateRoute({ children }) {
  const { loggedIn } = useContext(AuthContext)
  // 已登录返回子组件,未登录重定向到登录页,replace参数避免登录后回退到登录页
  return loggedIn ? children : <Navigate to="/login" replace />
}

4. Contexts.js 无需修改,保持原有配置即可

import { createContext } from "react";

export const TableCountContext = createContext(null)
export const AuthContext = createContext(false)

修改后即可实现需求:未登录用户访问任意受保护路由都会被重定向到登录页,侧边栏仅在登录后展示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:54:06