單一登入 (SSO) 是一種身份驗證機制,允許使用者登入一次並存取多個連接的應用程式或系統,而無需對每個應用程式或系統進行重新驗證。 SSO 將使用者驗證集中到單一受信任的系統(通常稱為身分提供者或IdP)中,然後該系統管理憑證並頒發令牌或會話資料以跨其他服務(稱為服務提供者或SP)驗證用戶的身份。 🎜>
在本指南中,我們將探討SSO 的工作原理、其優點和缺點、常見用例以及API(帶有Express 的Node.js)、主應用程式(React) 和外部應用程式中SSO 實現的範例應用程式(反應)。透過了解 SSO 的原理和實踐,組織可以增強其應用程式和系統的使用者體驗、安全性和營運效率。目錄
單一登入 (SSO)
SSO 將使用者驗證集中到單一受信任的系統(通常稱為身分提供者或IdP)中,然後該系統管理憑證並頒發令牌或會話數據,以跨其他服務(稱為服務提供者或SP)驗證使用者身分).
單一登入如何運作?
增強的使用者體驗:使用者只需一次登入即可存取多項服務,減少摩擦並提高可用性。
提高安全性:
簡化的使用者管理:
時間與成本效率:
合規與審核:
單點故障:
複雜的實作:
安全風險:
供應商鎖定:
代幣管理挑戰:
企業應用:
雲端服務:
客戶入口網站:
合作夥伴整合:
API 充當身分提供者 (IdP)。它對使用者進行身份驗證並頒發 JWT 令牌進行存取。
以下是所提供程式碼的結構化細分,為您的追蹤者解釋了每個部分的目的。這是如何在 API 層實現 SSO 功能的可靠範例。
此設定中使用了以下軟體包:
dotenv.config(); const SECRET_KEY = process.env.SECRET_KEY || "secret";
app.use( cors({ origin: ["http://localhost:5173", "http://localhost:5174"], credentials: true, }) ); app.use(express.json()); app.use(cookieParser());
模擬資料模擬使用者及其關聯的待辦事項。
使用者擁有角色(管理員或使用者)和基本個人資料資訊。
待辦事項連結到使用者 ID 以進行個人化存取。
使用者成功登入後會收到包含 JWT 的 cookie (sso_token)。
該令牌是安全的、僅限 HTTP 且有時間限制以防止篡改。
app.post("/login", (req, res) => { const { email, password } = req.body; const user = users.find( (user) => user.email === email && user.password === password ); if (user) { const token = jwt.sign({ user }, SECRET_KEY, { expiresIn: "1h" }); res.cookie("sso_token", token, { httpOnly: true, secure: process.env.NODE_ENV === "production", maxAge: 3600000, sameSite: "strict", }); res.json({ message: "Login successful" }); } else { res.status(400).json({ error: "Invalid credentials" }); } });
app.get("/verify", (req, res) => { const token = req.cookies.sso_token; if (!token) { return res.status(401).json({ authenticated: false }); } try { const decoded = jwt.verify(token, SECRET_KEY); res.json({ authenticated: true, user: decoded }); } catch { res.status(401).json({ authenticated: false, error: "Invalid token" }); } });
確保使用者可以透過清除令牌來安全地登出。
dotenv.config(); const SECRET_KEY = process.env.SECRET_KEY || "secret";
app.use( cors({ origin: ["http://localhost:5173", "http://localhost:5174"], credentials: true, }) ); app.use(express.json()); app.use(cookieParser());
app.post("/login", (req, res) => { const { email, password } = req.body; const user = users.find( (user) => user.email === email && user.password === password ); if (user) { const token = jwt.sign({ user }, SECRET_KEY, { expiresIn: "1h" }); res.cookie("sso_token", token, { httpOnly: true, secure: process.env.NODE_ENV === "production", maxAge: 3600000, sameSite: "strict", }); res.json({ message: "Login successful" }); } else { res.status(400).json({ error: "Invalid credentials" }); } });
app.get("/verify", (req, res) => { const token = req.cookies.sso_token; if (!token) { return res.status(401).json({ authenticated: false }); } try { const decoded = jwt.verify(token, SECRET_KEY); res.json({ authenticated: true, user: decoded }); } catch { res.status(401).json({ authenticated: false, error: "Invalid token" }); } });
app.post("/logout", (req, res) => { res.clearCookie("sso_token"); res.json({ message: "Logout successful" }); });
主應用程式充當服務提供者 (SP),使用 API 並管理使用者互動。
以下是所提供程式碼的結構化細分,為您的追蹤者解釋了每個部分的目的。這是如何在主應用程式層中實現 SSO 功能的可靠範例。
App 元件管理使用者驗證並根據登入狀態進行重新導向。
app.get("/todos/:userId", (req, res) => { const ssoToken = req.cookies.sso_token; const user = getUser(ssoToken); if (!user) { return res.status(401).json({ error: "Unauthorized" }); } const userTodos = todos.filter((todo) => todo.userId === user.id); res.json(userTodos); });
登入元件處理使用者登入並在驗證成功後重定向到 Todos 頁面。
app.post("/todos", (req, res) => { const ssoToken = req.cookies.sso_token; const user = getUser(ssoToken); if (!user) { return res.status(401).json({ error: "Unauthorized" }); } const { title, description } = req.body; const newTodo = { id: faker.string.uuid(), userId: user.id, title, description, }; todos.push(newTodo); res.status(201).json({ message: "Todo added successfully", data: newTodo }); });
Todos 元件顯示使用者特定的待辦事項並允許新增和刪除待辦事項。
// Update a todo app.put("/todos/:id", (req, res) => { const ssotoken = req.cookies.sso_token; const user = getUser(ssotoken); if (!user) { return res.status(401).json({ message: "Unauthorized" }); } const { id } = req.params; const { title, description } = req.body; const index = todos.findIndex((todo) => todo.id === id); if (index !== -1) { todos[index] = { ...todos[index], title, description, }; res.json({ message: "Todo updated successfully", data: todos[index], }); } else { res.status(404).json({ message: "Todo not found" }); } });
外部應用程式充當另一個服務提供者 (SP),使用 API 並管理使用者互動。
以下是所提供程式碼的結構化細分,為您的追蹤者解釋了每個部分的目的。這是如何在外部應用程式層實現 SSO 功能的可靠範例。
App 元件管理使用者驗證並根據登入狀態進行重新導向。
// Delete a todo app.delete("/todos/:id", (req, res) => { const ssoToken = req.cookies.sso_token; const user = getUser(ssoToken); if (!user) { return res.status(401).json({ message: "Unauthorized" }); } const { id } = req.params; const index = todos.findIndex((todo) => todo.id === id); if (index !== -1) { todos = todos.filter((todo) => todo.id !== id); res.json({ message: "Todo deleted successfully" }); } else { res.status(404).json({ message: "Todo not found" }); } });
Todos 元件顯示使用者特定的待辦事項。
import { useState, useEffect } from "react"; import { Navigate, Route, Routes, useNavigate, useSearchParams, } from "react-router-dom"; import Todos from "./components/Todos"; import Login from "./components/Login"; import { toast } from "react-toastify"; import api from "./api"; function App() { const [isLoggedIn, setIsLoggedIn] = useState(false); const [searchParams] = useSearchParams(); const navigate = useNavigate(); useEffect(() => { const verifyLogin = async () => { const returnUrl = searchParams.get("returnUrl"); try { const response = await api.get("/verify", { withCredentials: true, }); if (response.data.authenticated) { setIsLoggedIn(true); toast.success("You are logged in."); navigate("/todos"); } else { setIsLoggedIn(false); if (!returnUrl) { toast.error("You are not logged in."); } } } catch (error) { setIsLoggedIn(false); console.error("Verification failed:", error); } }; verifyLogin(); const handleVisibilityChange = () => { if (document.visibilityState === "visible") { verifyLogin(); } }; document.addEventListener("visibilitychange", handleVisibilityChange); return () => { document.removeEventListener("visibilitychange", handleVisibilityChange); }; }, [navigate, searchParams]); return ( <div className="container p-4 mx-auto"> <Routes> <Route path="/" element={<Login />} /> <Route path="/todos" element={isLoggedIn ? <Todos /> : <Navigate to={"/"} />} /> </Routes> </div> ); } export default App;
單一登入 (SSO) 簡化了跨多個應用程式的使用者驗證和存取管理,從而增強了使用者體驗、安全性和營運效率。透過集中身份驗證並利用基於安全性令牌的機制,組織可以簡化使用者存取、降低與密碼相關的風險並提高合規性和審核能力。
雖然 SSO 提供了眾多好處,但它也帶來了挑戰,例如單點故障、複雜的實施要求、安全風險和潛在的供應商鎖定。組織必須仔細規劃和實施 SSO 解決方案,以減輕這些風險並最大限度地發揮集中式身分驗證的優勢。
透過遵循最佳實踐、利用既定協議並選擇開放標準,組織可以成功實施 SSO,以增強其應用程式和系統的使用者體驗、安全性和營運效率。
以上是單一登入 (SSO):React 和 ExpressJS 綜合指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!