尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
单点登录原理与简单实现
单点登录原理与简单实现引言为什么需要单点登录在互联网应用中一个大型系统往往由多个子系统组成如用户中心、订单系统、支付系统。如果每个子系统都独立维护登录状态用户需要在每个系统中重复输入账号密码体验极差。单点登录Single Sign-On简称SSO正是为了解决这个问题而诞生——用户只需登录一次即可访问所有相互信任的子系统。### 一、单点登录的核心原理SSO的核心思想是将用户的登录状态集中管理在一个独立的认证中心Auth Server所有子系统不再直接处理登录逻辑而是通过认证中心验证用户身份。一次完整的SSO交互流程如下1.用户访问子系统AA发现用户未登录重定向到认证中心。2.认证中心检查用户是否已登录。若未登录展示登录页面。3.用户输入凭证认证中心验证成功后生成一个全局会话Global Session并颁发一个授权票据Ticket。4.认证中心带着Ticket重定向回子系统AA拿着Ticket到认证中心验证有效性。5.验证通过后A为当前用户创建本地会话如Session或Token。6.用户再访问子系统BB同样重定向到认证中心。此时认证中心发现用户已有全局会话直接颁发新Ticket无需再次登录。关键组件认证中心负责登录、全局会话管理、票据颁发与验证、各子系统负责本地会话创建与验证。—### 二、从零实现一个简易SSO系统我们使用Python Flask来实现一个最小可用的SSO示例。为了让代码清晰我们拆分为两个部分认证中心auth_server.py和两个模拟业务子系统app_a.py、app_b.py。#### 2.1 认证中心Auth Server认证中心负责处理登录、发放票据、验证票据。我们使用内存字典存储已登录用户和有效票据生产环境应使用Redis等共享存储。python# auth_server.pyfrom flask import Flask, request, redirect, session, jsonifyimport uuidapp Flask(__name__)app.secret_key auth_server_secret# 模拟用户数据库USERS {alice: 123456, bob: abcdef}# 存储有效票据key为ticketvalue为usernameTICKETS {}app.route(/login)def login(): # 如果已全局登录直接跳转回子系统 if username in session: return redirect_to_subsystem() # 否则展示登录页面这里用简单HTML return form methodpost action/do_login 用户名: input nameusernamebr 密码: input namepassword typepasswordbr button typesubmit登录/button /form app.route(/do_login, methods[POST])def do_login(): username request.form[username] password request.form[password] if USERS.get(username) password: session[username] username # 生成票据并关联用户名 ticket uuid.uuid4().hex TICKETS[ticket] username return redirect_to_subsystem(ticket) return 登录失败, 401def redirect_to_subsystem(ticketNone): # 从请求参数中获取子系统回调地址 redirect_url request.args.get(redirect_url) if redirect_url: # 拼接ticket separator if ? in redirect_url else ? return redirect(f{redirect_url}{separator}ticket{ticket or }) return 登录成功app.route(/verify_ticket)def verify_ticket(): # 子系统验证票据的接口 ticket request.args.get(ticket) username TICKETS.pop(ticket, None) # 一次性使用 if username: return jsonify({valid: True, username: username}) return jsonify({valid: False})if __name__ __main__: app.run(port5000)#### 2.2 业务子系统A模拟子系统A不处理用户密码只负责跳转到认证中心并验证票据后创建本地会话。python# app_a.pyfrom flask import Flask, session, request, redirect, jsonifyimport requestsapp Flask(__name__)app.secret_key app_a_secretAUTH_SERVER http://localhost:5000app.route(/)def home(): # 检查本地会话 if username in session: return f欢迎{session[username]}这是系统A的首页。 # 未登录重定向到认证中心带上回调地址 redirect_url f{AUTH_SERVER}/login?redirect_url{request.url} return redirect(redirect_url)app.route(/callback)def callback(): # 认证中心跳转回来携带ticket ticket request.args.get(ticket) if not ticket: return 缺少票据, 400 # 向认证中心验证票据 resp requests.get(f{AUTH_SERVER}/verify_ticket, params{ticket: ticket}) data resp.json() if data.get(valid): session[username] data[username] return redirect(/) return 票据无效, 401if __name__ __main__: app.run(port5001)#### 2.3 业务子系统B模拟子系统B的代码与A几乎相同只需修改端口号例如5002。为了节省篇幅这里只列出关键修改点python# app_b.py核心逻辑与app_a相同仅端口差异# 只需将 app.run(port5002) 即可# 其余代码完全一致—### 三、运行与测试1. 安装Flask和requestspip install flask requests2. 分别启动三个服务python auth_server.py端口5000python app_a.py端口5001python app_b.py端口5002。3. 浏览器访问http://localhost:5001会被重定向到认证中心输入用户名alice密码123456登录。4. 登录成功后自动跳回系统A首页显示欢迎信息。5. 此时再访问http://localhost:5002会发现无需登录直接进入系统B因为认证中心已有全局会话。—### 四、关键细节与进阶设计#### 4.1 票据的安全性上述示例中票据是随机UUID但实际生产环境需要考虑-过期时间票据应设置有效期如5分钟。-一次性使用验证后立即销毁防止重放攻击。-签名使用JWTJSON Web Token或HMAC签名防止篡改。#### 4.2 会话存储的扩展认证中心的全局会话和票据若存于内存重启即丢失。生产环境应使用Redis集群并设置合理的过期策略。#### 4.3 跨域问题如果子系统与认证中心不在同一域名下浏览器默认会拦截Cookie传递。解决方案包括- 使用前端iframe postMessage实现跨域会话保持。- 使用JSONP或CORS进行票据传递。- 采用OAuth2或OIDC协议它们天然支持跨域。#### 4.4 令牌Token模式现代SSO更倾向于使用JWT作为令牌认证中心签发JWT后子系统通过公钥验证签名无需每次请求都回认证中心校验。这大大降低了认证中心的压力。python# JWT示例示意import jwttoken jwt.encode({user: alice, exp: 123456789}, secret, algorithmHS256)# 子系统用同样的secret解码验证—### 五、总结单点登录解决了多系统间身份认证的统一问题核心在于集中认证票据传递。本文从原理出发用Flask实现了一个最小可运行的SSO示例并讨论了生产环境中的安全性和扩展性问题。实际项目中建议直接采用成熟的协议如OAuth2、SAML、CAS或云服务如Auth0、Keycloak避免重复造轮子。理解底层原理有助于我们更好地使用这些工具并在出现问题时快速定位。希望本文能帮助你建立对SSO的清晰认知。
RELATED

相关推荐

职场交易思维:价值交换与生存法则

职场交易思维:价值交换与生存法则

1. 职场本质的重新认知"上班是一场冷静的交易"这个说法最近在职场圈子里流传甚广。作为在互联网行业摸爬滚打十年的老鸟,我对这句话有着深刻体会。它直指现代职场关系的核心本质——雇佣关系本质上就是一场价值交换。我刚入行时也抱着"为公司奉献一切…

📅 2026/9/30 8:12:28
企业AI Agent安全治理:从幽灵运维到合规创新的实战指南

企业AI Agent安全治理:从幽灵运维到合规创新的实战指南

1. 项目概述:当“幽灵”在服务器间游荡最近和几个做企业安全的朋友聊天,他们不约而同地提到了一个让人后背发凉的现象:公司内部的服务器上,开始出现一些“来历不明”的进程和定时任务。这些任务并非由运维团队部署,却能…

📅 2026/9/11 8:59:21
Layerdivider:3分钟将任何图片变成可编辑PSD图层的终极指南 [特殊字符]

Layerdivider:3分钟将任何图片变成可编辑PSD图层的终极指南 [特殊字符]

Layerdivider:3分钟将任何图片变成可编辑PSD图层的终极指南 🎨 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider 你是否曾经拿到一张…

📅 2026/9/26 10:32:29
MORE NEWS

更多资讯

📰

伪代码中无用函数返回值:接口语义的减法与代码整洁

从代码整洁到团队协作:我为什么坚持删掉伪代码里那些没用的返回值 先说结论:工作这些年,我越来越觉得伪代码里的“函数返回值”不是随便写的。它就像程序设计时的“契约”,哪怕只是画草图,契约里没用的条款也会让人误…

📰

基于Golang的网络安全靶场:Gin+Gorm+Docker实战指南

简介:这份文档面向网络安全方向的学生、安全运维人员及攻防技术爱好者,围绕基于Golang的网络安全靶场系统展开完整设计与实现论述,帮助读者理解如何用Go语言搭建可模拟、复现网络攻击的实验环境,从而在实战中掌握攻击手法并推导对…

📰

Flutter鸿蒙适配实战:消息反馈系统的跨端实现与踩坑

先把结论放在前面:一个 Flutter 项目要上一个新平台,最麻烦的从来不是把页面跑起来,而是那些要跟系统原生能力打交道的模块。消息反馈就是这样一类典型模块——表面上不过是一个“表单加列表”,真正落地的时候,通知、角…

📰

Flutter鸿蒙版消息反馈系统开发实践:架构设计与踩坑记录

做鸿蒙版App的时候,团队在技术选型上纠结了挺久。最后定下来用Flutter构建“享家社区”的HarmonyOS APP,而且第一个完整跑通的模块,就是消息反馈系统。这个模块看着不起眼,却是社区类产品里最容易暴露问题的一环:用户要…

📰

Gradio生产级ML应用实战:从Demo到K8s部署的完整工程化指南

几个月前我给公司的推荐模型搭了个临时演示页面,用 Gradio 写了个两百行的脚本,拖个滑块、传张图就能看推理结果。当时产品经理说“这玩意能直接上线就好了”,我嘴上应付着“快了快了”,心里清楚这套代码连最基本的身份校验都没有…

📰

Anaconda虚拟环境底层原理与PyCharm配置真相

1. 为什么你每次在PyCharm里跑代码都报“ModuleNotFoundError”,而同事的项目却稳如泰山? 我见过太多人把Python开发环境搞成“玄学现场”:明明pip install了requests,运行时却提示找不到;换台电脑重装一遍&#xff0c…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬