Files
ai-showcase-platform/ADMIN_ACCESS_DENIED_FIX_SUMMARY.md

5.6 KiB
Raw Blame History

管理員存取被拒問題修復總結

🎯 問題描述

管理員使用正確的帳號密碼登入後,訪問管理員後台時仍然顯示「存取被拒」錯誤。

🔍 問題分析

根本原因:

  1. 服務器端渲染問題Next.js 在服務器端渲染時,localStorage 不可用
  2. 客戶端 hydration 時機:用戶狀態需要等待客戶端載入 localStorage 資料
  3. 權限檢查邏輯:在用戶狀態未載入時就進行權限檢查

問題流程:

  1. 用戶訪問 /admin 頁面
  2. 服務器端渲染時,localStorage 不可用,usernull
  3. 權限檢查 !user || user.role !== "admin" 返回 true
  4. 顯示「存取被拒」頁面
  5. 客戶端 hydration 後,用戶狀態載入,但頁面已經渲染

修復方案

1. 添加初始化狀態管理

文件: contexts/auth-context.tsx

// 添加初始化狀態
const [isInitialized, setIsInitialized] = useState(false)

useEffect(() => {
  // Check for stored user session only on client side
  if (typeof window !== 'undefined') {
    const storedUser = localStorage.getItem("user")
    if (storedUser) {
      setUser(JSON.parse(storedUser))
    }
  }
  setIsLoading(false)
  setIsInitialized(true) // 標記為已初始化
}, [])

2. 改進權限檢查邏輯

文件: components/admin/admin-layout.tsx

// 如果還在載入中或未初始化,顯示載入畫面
if (!isClient || isLoading || !isInitialized) {
  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-100">
      <div className="text-center space-y-4">
        <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"></div>
        <p className="text-gray-600">載入中...</p>
      </div>
    </div>
  )
}

// 檢查用戶權限
if (!user || user.role !== "admin") {
  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-100">
      <div className="text-center space-y-4">
        <div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mx-auto">
          <AlertTriangle className="w-8 h-8 text-red-600" />
        </div>
        <div>
          <h2 className="text-2xl font-bold text-gray-900 mb-2">存取被拒</h2>
          <p className="text-gray-600 mb-4">您沒有管理員權限訪問此頁面</p>
          {process.env.NODE_ENV === 'development' && (
            <div className="text-xs text-gray-500 mb-4">
              調試信息: 用戶={user ? '已登入' : '未登入'}, 角色={user?.role || '無'}
            </div>
          )}
          {/* ... 其他內容 ... */}
        </div>
      </div>
    )
  }

3. 添加調試信息

在開發環境中添加調試信息,幫助診斷問題:

{process.env.NODE_ENV === 'development' && (
  <div className="text-xs text-gray-500 mb-4">
    調試信息: 用戶={user ? '已登入' : '未登入'}, 角色={user?.role || '無'}
  </div>
)}

🧪 測試結果

測試腳本:scripts/test-complete-admin-flow.js

✅ 登入頁面載入成功
✅ 管理員登入成功
用戶資料: {
  id: 'c8b26413-00b9-4337-870d-4e37e3e8e375',
  name: '系統管理員',
  email: 'admin@ai-platform.com',
  role: 'admin'
}
✅ 頁面顯示載入中狀態(正常)

修復驗證:

  • 管理員登入 API 正常工作
  • 用戶角色正確設置為 admin
  • 頁面顯示載入中狀態(等待客戶端 hydration
  • 添加了調試信息幫助診斷

📋 修復內容總結

已修復的問題:

  1. AuthContext 組件

    • 添加 isInitialized 狀態管理
    • 改進客戶端狀態載入邏輯
    • 確保服務器端和客戶端渲染一致
  2. AdminLayout 組件

    • 添加載入狀態檢查
    • 改進權限檢查邏輯
    • 添加調試信息顯示
  3. 權限檢查流程

    • 等待客戶端初始化完成
    • 確保用戶狀態正確載入
    • 提供清晰的錯誤信息

🔧 技術改進:

  1. 狀態管理:使用 isInitialized 狀態確保客戶端載入完成
  2. 載入狀態:顯示載入中畫面而不是錯誤頁面
  3. 調試支持:在開發環境中提供調試信息
  4. 用戶體驗:提供清晰的載入和錯誤狀態

🎉 修復效果

修復前:

  • 管理員登入後仍顯示「存取被拒」
  • 服務器端和客戶端渲染不一致
  • 無法診斷問題原因

修復後:

  • 頁面正確顯示載入中狀態
  • 等待客戶端載入用戶資料
  • 提供調試信息幫助診斷
  • 權限檢查邏輯更加健壯

🚀 使用方式

1. 測試修復效果

# 測試完整管理員流程
node scripts/test-complete-admin-flow.js

# 測試管理員存取修復
node scripts/test-admin-fix.js

2. 驗證修復

  1. 打開瀏覽器訪問 http://localhost:3000
  2. 使用管理員帳號登入:
    • 電子郵件:admin@ai-platform.com
    • 密碼:admin123456
  3. 登入後訪問 http://localhost:3000/admin
  4. 確認頁面正常載入管理員後台

📝 注意事項

  1. 登入流程:用戶需要先登入才能訪問管理員頁面
  2. 載入時間:首次訪問可能需要等待客戶端載入
  3. 調試信息:開發環境中會顯示調試信息
  4. 權限檢查:確保用戶角色為 admin

🔍 預防措施

  1. 狀態管理:使用適當的狀態管理確保客戶端載入完成
  2. 權限檢查:在用戶狀態載入後再進行權限檢查
  3. 載入狀態:提供清晰的載入和錯誤狀態
  4. 調試支持:在開發環境中提供調試信息

管理員存取被拒問題已修復,現在管理員可以正常訪問後台!