单点登录 (SSO) 是一种身份验证机制,允许用户登录一次并访问多个连接的应用程序或系统,而无需对每个应用程序或系统进行重新身份验证。 SSO 将用户身份验证集中到单个受信任的系统(通常称为身份提供商或 IdP)中,然后该系统管理凭据并颁发令牌或会话数据以跨其他服务(称为服务提供商或 SP)验证用户的身份。 🎜>
在本指南中,我们将探讨 SSO 的工作原理、其优点和缺点、常见用例以及 API(带有 Express 的 Node.js)、主应用程序 (React) 和外部应用程序中 SSO 实现的示例应用程序(反应)。通过了解 SSO 的原理和实践,组织可以增强其应用程序和系统的用户体验、安全性和运营效率。目录
-
单点登录 (SSO)
-
- SSO 如何工作?
- SSO 的好处
- SSO 的缺点
- SSO 用例
- SSO 实施示例
- 1. API(带有 Express 的 Node.js)
- 2.主要应用程序(React)
- 3.外部应用程序(React)
结论
- GitHub 存储库
单点登录 (SSO) 是一种身份验证机制,允许用户登录一次即可访问多个连接的应用程序或系统,而无需对每个应用程序或系统进行重新身份验证。
SSO 将用户身份验证集中到单个受信任的系统(通常称为身份提供商或 IdP)中,然后该系统管理凭据并颁发令牌或会话数据,以跨其他服务(称为服务提供商或 SP)验证用户身份).
单点登录如何工作?
SSO 通过基于安全令牌的机制(例如 OAuth 2.0、OpenID Connect (OIDC) 或安全断言标记语言 (SAML))进行操作。这是一个简化的流程:
- 用户登录:用户在身份提供商 (IdP) 中输入其凭据。
- 令牌颁发:IdP 验证凭据并颁发身份验证令牌(例如 JWT 或 SAML 断言)。
- 服务访问:令牌被传递给服务提供商,服务提供商对其进行验证并授予访问权限,而无需进一步登录。
-
增强的用户体验:用户只需一次登录即可访问多项服务,减少摩擦并提高可用性。
-
提高安全性:
- 减少密码疲劳,避免密码重复使用等不安全行为。
- 集中式身份验证可实现更强大的密码策略并实施多重身份验证 (MFA)。
-
简化的用户管理:
- 管理员可以更轻松地管理跨连接应用程序的用户访问。
- 从 IdP 撤销对用户的访问权限会禁用他们对所有集成系统的访问权限。
-
时间和成本效率:
- 通过减少与登录相关的帮助台请求,为用户和支持团队节省时间。
- 通过利用现有的身份验证机制减少开发时间和成本。
-
合规与审核:
- 集中式身份验证和访问控制使执行安全策略和跟踪用户活动变得更加容易。
单点登录的缺点
-
单点故障:
- 如果 IdP 不可用或受到威胁,用户将无法访问任何连接的系统。
- 缓解措施:使用冗余 IdP 并确保高可用性。
-
复杂的实现:
- 集成 SSO 需要大量的规划和专业知识,尤其是在具有不同应用程序和协议的环境中。
- 缓解措施:利用 OAuth 2.0 或 SAML 等既定协议以及强大的 SSO 库。
-
安全风险:
- 如果攻击者获得对用户 SSO 凭据的访问权限,他们就有可能访问所有连接的系统。
- 缓解措施:实施强大的 MFA 并监控可疑的登录活动。
-
供应商锁定:
- 组织可能严重依赖特定的 IdP 供应商,这使得迁移充满挑战。
- 缓解措施:选择开放标准并避免专有解决方案。
-
代币管理挑战:
- 过期或被盗的令牌可能会中断访问或造成安全漏洞。
- 缓解措施:实施令牌过期、刷新机制和安全令牌存储。
SSO 用例
-
企业应用:
- 员工只需登录即可访问各种内部工具和服务。
- 简化入职和离职流程。
-
云服务:
- 用户可以在云应用之间无缝切换,无需重复登录。
- 提高生产力和用户体验。
-
客户门户:
- 为不同服务的客户提供统一的登录体验。
- 实现个性化和有针对性的营销。
-
合作伙伴集成:
- 促进对合作伙伴组织之间共享资源的安全访问。
- 简化协作和数据交换。
SSO 实施示例
1. API(Node.js 和 Express)
API 充当身份提供商 (IdP)。它对用户进行身份验证并颁发 JWT 令牌进行访问。
下面是所提供代码的结构化细分,为您的关注者解释了每个部分的目的。这是如何在 API 层实现 SSO 功能的可靠示例。
设置和依赖关系
此设置中使用了以下软件包:
- express:用于处理 HTTP 请求和路由。
- jsonwebtoken:用于生成和验证 JWT。
- cors:用于处理来自不同客户端应用程序的跨源请求。
- @faker-js/faker:用于生成模拟用户和待办事项数据。
- cookie-parser:用于解析请求中发送的cookie。
- dotenv:用于安全地加载环境变量。
配置
- dotenv 用于安全地管理密钥。
- 为开发环境提供了后备秘密。
dotenv.config(); const SECRET_KEY = process.env.SECRET_KEY || "secret";
中间件
- CORS 确保允许来自特定前端来源(主应用程序和外部应用程序)的请求。
- cookieParser 解析客户端发送的 cookie。
- express.json 允许解析 JSON 请求主体。
app.use( cors({ origin: ["http://localhost:5173", "http://localhost:5174"], credentials: true, }) ); app.use(express.json()); app.use(cookieParser());
用户身份验证和令牌生成
模拟数据模拟用户及其关联的待办事项。
用户拥有角色(管理员或用户)和基本个人资料信息。
待办事项链接到用户 ID 以进行个性化访问。
- /login:根据电子邮件和密码对用户进行身份验证。
用户成功登录后会收到包含 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" }); } });
- /verify:通过解码令牌来验证用户的身份。无效令牌会导致未经授权的响应。
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" }); } });
- /logout:清除包含 JWT 令牌的 cookie。
确保用户可以通过清除令牌来安全注销。
dotenv.config(); const SECRET_KEY = process.env.SECRET_KEY || "secret";
- /todos:检索与经过身份验证的用户关联的待办事项。
app.use( cors({ origin: ["http://localhost:5173", "http://localhost:5174"], credentials: true, }) ); app.use(express.json()); app.use(cookieParser());
- /todos:为经过身份验证的用户添加新的待办事项。
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" }); } });
- /todos/:id:根据提供的 ID 更新待办事项。
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" }); } });
- /todos/:id:根据提供的 ID 删除待办事项。
app.post("/logout", (req, res) => { res.clearCookie("sso_token"); res.json({ message: "Logout successful" }); });
2. 主要应用程序(React)
主应用程序充当服务提供商 (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" }); } });
3. 外部应用程序(React)
外部应用程序充当另一个服务提供商 (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>} /> <route path="/todos" element="{isLoggedIn"></route> : <navigate to='{"/"}'></navigate>} /> </routes> </div> ); } export default App;
结论
单点登录 (SSO) 简化了跨多个应用程序的用户身份验证和访问管理,从而增强了用户体验、安全性和运营效率。通过集中身份验证并利用基于安全令牌的机制,组织可以简化用户访问、降低与密码相关的风险并提高合规性和审核能力。
虽然 SSO 提供了众多好处,但它也带来了挑战,例如单点故障、复杂的实施要求、安全风险和潜在的供应商锁定。组织必须仔细规划和实施 SSO 解决方案,以减轻这些风险并最大限度地发挥集中式身份验证的优势。
通过遵循最佳实践、利用既定协议并选择开放标准,组织可以成功实施 SSO,以增强其应用程序和系统的用户体验、安全性和运营效率。
以上是单点登录 (SSO):React 和 ExpressJS 综合指南的详细内容。更多信息请关注PHP中文网其他相关文章!

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

Dreamweaver CS6
视觉化网页开发工具

Atom编辑器mac版下载
最流行的的开源编辑器

SublimeText3汉化版
中文版,非常好用

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。