iT邦幫忙

2025 iThome 鐵人賽

DAY 17
0
Modern Web

不只是登入畫面!一起打造現代化登入系統系列 第 17

屋內安全[ 6 / 7 ]:AuthContext + Protected Route 實作

  • 分享至 

  • xImage
  •  

把 Token 丟去 /auth/verify 只是「確認他是不是合法使用者」,但接下來還有兩件事要處理:

  1. 把驗證結果存起來(避免每次重新整理都重發 API)
  2. 限制未登入的人進入某些頁面(例如 /dashboard、/profile)

這一節會用 React 最常見的做法:AuthContext + ProtectedRoute 組合拳
不需要上 Redux、不用引入額外套件,小專案、中型應用都適用。


1. 建立 AuthContext(管理登入狀態)

import { createContext, useContext, useState, useEffect } from "react";
import { useVerifyToken } from "../hooks/useVerifyToken";

const AuthContext = createContext(null);

export const AuthProvider = ({ children }) => {
  const { verifyToken } = useVerifyToken();
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  // 初始化時就驗證一次
  useEffect(() => {
    const checkToken = async () => {
      try {
        const data = await verifyToken();
        setUser(data); // { uid, email ... }
      } catch {
        setUser(null);
      } finally {
        setLoading(false);
      }
    };

    checkToken();
  }, []);

  return (
    <AuthContext.Provider value={{ user, loading, setUser }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext);

這樣做的好處是:
✅ App 一載入就會自動驗證 Token
✅ 驗證結果會存起來、不會重複打 API
✅ 之後要登出或重新驗證也方便


2. 建立「ProtectedRoute」元件

import { Navigate } from "react-router-dom";
import { useAuth } from "../contexts/AuthContext";

export default function ProtectedRoute({ children }) {
  const { user, loading } = useAuth();

  if (loading) return <p>驗證中...</p>;

  return user ? children : <Navigate to="/login" replace />;
}

3. 把它掛進 React Router

import { Routes, Route } from "react-router-dom";
import ProtectedRoute from "./components/ProtectedRoute";
import Dashboard from "./pages/Dashboard";
import Login from "./pages/Login";

export default function AppRoutes() {
  return (
    <Routes>
      <Route path="/login" element={<Login />} />

      <Route
        path="/dashboard"
        element={
          <ProtectedRoute>
            <Dashboard />
          </ProtectedRoute>
        }
      />
    </Routes>
  );
}

4. 記得把 AuthProvider 包在最外層

import ReactDOM from "react-dom/client";
import AppRoutes from "./App";
import { AuthProvider } from "./contexts/AuthContext";

ReactDOM.createRoot(document.getElementById("root")).render(
  <AuthProvider>
    <AppRoutes />
  </AuthProvider>
);

上一篇
屋內安全[ 4 / 6 ]:React 串接驗證流程實作
下一篇
屋內安全[ 7 / 7 ]:Token 要放哪裡?LocalStorage、Cookie、Memory 的優缺點與實作方式
系列文
不只是登入畫面!一起打造現代化登入系統18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言