5.6 KiB
5.6 KiB
管理員存取被拒問題修復總結
🎯 問題描述
管理員使用正確的帳號密碼登入後,訪問管理員後台時仍然顯示「存取被拒」錯誤。
🔍 問題分析
根本原因:
- 服務器端渲染問題:Next.js 在服務器端渲染時,
localStorage
不可用 - 客戶端 hydration 時機:用戶狀態需要等待客戶端載入
localStorage
資料 - 權限檢查邏輯:在用戶狀態未載入時就進行權限檢查
問題流程:
- 用戶訪問
/admin
頁面 - 服務器端渲染時,
localStorage
不可用,user
為null
- 權限檢查
!user || user.role !== "admin"
返回true
- 顯示「存取被拒」頁面
- 客戶端 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)
- ✅ 添加了調試信息幫助診斷
📋 修復內容總結
✅ 已修復的問題:
-
AuthContext 組件
- 添加
isInitialized
狀態管理 - 改進客戶端狀態載入邏輯
- 確保服務器端和客戶端渲染一致
- 添加
-
AdminLayout 組件
- 添加載入狀態檢查
- 改進權限檢查邏輯
- 添加調試信息顯示
-
權限檢查流程
- 等待客戶端初始化完成
- 確保用戶狀態正確載入
- 提供清晰的錯誤信息
🔧 技術改進:
- 狀態管理:使用
isInitialized
狀態確保客戶端載入完成 - 載入狀態:顯示載入中畫面而不是錯誤頁面
- 調試支持:在開發環境中提供調試信息
- 用戶體驗:提供清晰的載入和錯誤狀態
🎉 修復效果
修復前:
- 管理員登入後仍顯示「存取被拒」
- 服務器端和客戶端渲染不一致
- 無法診斷問題原因
修復後:
- 頁面正確顯示載入中狀態
- 等待客戶端載入用戶資料
- 提供調試信息幫助診斷
- 權限檢查邏輯更加健壯
🚀 使用方式
1. 測試修復效果
# 測試完整管理員流程
node scripts/test-complete-admin-flow.js
# 測試管理員存取修復
node scripts/test-admin-fix.js
2. 驗證修復
- 打開瀏覽器訪問
http://localhost:3000
- 使用管理員帳號登入:
- 電子郵件:
admin@ai-platform.com
- 密碼:
admin123456
- 電子郵件:
- 登入後訪問
http://localhost:3000/admin
- 確認頁面正常載入管理員後台
📝 注意事項
- 登入流程:用戶需要先登入才能訪問管理員頁面
- 載入時間:首次訪問可能需要等待客戶端載入
- 調試信息:開發環境中會顯示調試信息
- 權限檢查:確保用戶角色為
admin
🔍 預防措施
- 狀態管理:使用適當的狀態管理確保客戶端載入完成
- 權限檢查:在用戶狀態載入後再進行權限檢查
- 載入狀態:提供清晰的載入和錯誤狀態
- 調試支持:在開發環境中提供調試信息
管理員存取被拒問題已修復,現在管理員可以正常訪問後台!