当前位置: 首页 > news >正文

用 Python 实现一个简化但可运行的 单点登录(SSO)系统

好的!下面我将用 Python 实现一个简化但可运行的 单点登录(SSO)系统,其中:

  • A 系统 作为 身份提供商(IdP)
  • B 系统 作为 服务提供商(SP)
  • 用户在 A 登录后,点击链接跳转到 B,B 自动登录,无需输入密码

我们将使用:

  • Flask 作为 Web 框架
  • JWT(JSON Web Token) 作为 SSO 令牌
  • 加密签名 保证令牌不可伪造
  • HTTPS(本地用 HTTP 演示,生产务必用 HTTPS)

🧩 系统架构

用户浏览器│├── 访问 A 系统 → 登录 → 获得 session│└── 点击 "打开 B 系统" → 跳转到 A 的 /sso?target=B→ A 生成 JWT → 重定向到 B 的 /sso?token=xxx→ B 验证 JWT → 创建本地会话 → 展示页面

第一步:A 系统(IdP) — idp.py

# idp.py - A 系统(身份提供商)
from flask import Flask, request, redirect, url_for, session, render_template_string
import jwt
import time
import urllib.parseapp = Flask(__name__)
app.secret_key = 'super-secret-key-for-session'  # 用于 Flask session# JWT 签名密钥(A 和 B 必须共享!生产环境应使用安全存储)
JWT_SECRET = 'sso-shared-secret-2025'# 模拟用户数据库
USERS = {'alice': 'password123','bob': 'securepass'
}# A 系统首页(登录页)
@app.route('/')
def home():if 'user' in session:return render_template_string('''<h2>A 系统 - 已登录:{{ user }}</h2><a href="/sso?target={{ b_url }}">👉 打开 B 系统(SSO)</a><form method="post" action="/logout"><button>退出登录</button></form>''', user=session['user'], b_url='http://localhost:5001')return render_template_string('''<h2>A 系统 - 登录</h2><form method="post" action="/login">用户名: <input name="username"><br>密码: <input name="password" type="password"><br><button type="submit">登录</button></form>''')@app.route('/login', methods=['POST'])
def login():username = request.form['username']password = request.form['password']if USERS.get(username) == password:session['user'] = usernamereturn redirect('/')return '登录失败!', 401@app.route('/logout', methods=['POST'])
def logout():session.pop('user', None)return redirect('/')# SSO 接口:生成 JWT 并重定向到目标系统
@app.route('/sso')
def sso():if 'user' not in session:return redirect('/')  # 未登录则跳回首页target = request.args.get('target')if not target:return '缺少 target 参数', 400# 构造 JWT payloadpayload = {'sub': session['user'],          # 用户名'iss': 'A-System',               # 签发者'exp': int(time.time()) + 60,    # 60秒过期(生产可设为 30~120 秒)'iat': int(time.time()),'target': target                 # 可选:限制目标}# 生成 JWTtoken = jwt.encode(payload, JWT_SECRET, algorithm='HS256')# 重定向到 B 系统的 SSO 入口redirect_url = f"{target}/sso?token={urllib.parse.quote(token)}"return redirect(redirect_url)if __name__ == '__main__':# A 系统运行在 5000 端口app.run(port=5000, debug=True)

第二步:B 系统(SP) — sp.py

# sp.py - B 系统(服务提供商)
from flask import Flask, request, session, redirect, render_template_string
import jwt
import time
import urllib.parseapp = Flask(__name__)
app.secret_key = 'b-system-secret-session-key'# 必须与 A 系统的 JWT_SECRET 一致!
JWT_SECRET = 'sso-shared-secret-2025'@app.route('/')
def home():if 'user' in session:return render_template_string('''<h2>B 系统 - 欢迎 {{ user }}!</h2><p>✅ 你已通过 A 系统单点登录成功!</p><form method="post" action="/logout"><button>退出 B 系统</button></form>''', user=session['user'])else:return '''<h2>B 系统 - 未登录</h2><p>请通过 A 系统访问本系统。</p><a href="http://localhost:5000">前往 A 系统登录</a>'''# SSO 入口:接收并验证 JWT
@app.route('/sso')
def sso():token = request.args.get('token')if not token:return '缺少 token', 400try:# 解码并验证 JWTpayload = jwt.decode(token, JWT_SECRET, algorithms=['HS256'])# 检查是否过期(jwt.decode 自动验证 exp)# 可选:检查 iss 是否为 'A-System'if payload.get('iss') != 'A-System':return '无效签发者', 403# 可选:检查 target 是否匹配当前系统# target = payload.get('target')# if not target or 'localhost:5001' not in target:#     return '目标不匹配', 403# 创建 B 系统本地会话session['user'] = payload['sub']return redirect('/')except jwt.ExpiredSignatureError:return 'SSO 令牌已过期', 401except jwt.InvalidTokenError:return '无效的 SSO 令牌', 403@app.route('/logout', methods=['POST'])
def logout():session.pop('user', None)return redirect('/')if __name__ == '__main__':# B 系统运行在 5001 端口app.run(port=5001, debug=True)

第三步:运行与测试

1. 安装依赖

pip install flask PyJWT

2. 启动两个系统

# 终端 1
python idp.py      # A 系统,http://localhost:5000# 终端 2
python sp.py       # B 系统,http://localhost:5001

3. 测试流程

  1. 打开浏览器访问 http://localhost:5000
  2. 用用户名 alice、密码 password123 登录 A 系统
  3. 点击 “打开 B 系统(SSO)” 链接
  4. 自动跳转到 B 系统,并显示:

    B 系统 - 欢迎 alice!
    ✅ 你已通过 A 系统单点登录成功!

全程无需在 B 系统输入用户名密码!


🔒 安全增强建议(生产环境)

  1. 使用 HTTPS:防止 token 被窃听(本地开发可用 mkcert 生成证书)
  2. JWT 密钥安全存储:不要硬编码,使用环境变量或密钥管理服务
  3. 缩短 token 有效期:建议 30~60 秒
  4. 绑定用户上下文(可选):
    • 在 JWT 中加入 jti(唯一 ID)防止重放
    • 绑定 IP 或 User-Agent(但可能影响移动设备体验)
  5. 验证 target 参数:防止 token 被用于其他系统
  6. 日志审计:记录 SSO 登录事件

🔄 扩展方向

  • 支持多个 SP(C、D 系统):只需共享 JWT_SECRET 并实现 /sso 接口
  • 添加单点登出(SLO):A 登出时通知所有 SP
  • 使用 OpenID Connect 替代自定义 JWT(更标准)

这个实现虽然简化,但完整展示了 A 作为 IdP 实现 SSO 的核心逻辑。你可以在此基础上扩展为生产级系统。需要我帮你加上 HTTPS、数据库用户管理或 OIDC 支持吗?

http://www.dtcms.com/a/424496.html

相关文章:

  • 水果成篮-越短越合法
  • 外国人做的购物网站做网站开发要具备哪些素质
  • 印尼雅加达综合指数(JCI)数据对接实战指南
  • 福州网站开发公司哪些网站可以做平面设计
  • 临安规划建设局网站wordpress 评论按钮
  • 定向广播扬声器:高速公路预警新利器 为安全“喊话”
  • 做网站送优化如何做授权网站
  • 产品展示类网站网站用户体验度
  • 网站管理问题建站点的步骤
  • 安阳网站哪家做的好网站开发需要什么基础知识
  • 新乡定制网站建设公司网站建设属于
  • 网站建设技术和销售工资用手机建网站
  • 网站集群建设方案中国移动积分兑换商城官方网站
  • 怎么选择镇江网站建设WordPress影视cms
  • 网站建设的一般流程排序为湖南城乡建设部网站
  • 大数据数据质量校验实战指南:从0.3%差异率到滴水不漏的核对体系
  • 阜阳哪里做网站的多购物网站开发技术
  • OpenCASCADE 点云拟合曲线与曲面:从零实现到工业级应用
  • 【Axure教程】多角色登录原型
  • 深圳 德 网站建设安装wordpress报错
  • port default vlan vlan-id 概念及题目
  • 分布式任务调度系统设计方案
  • 惠州网站建设企业廊坊网站专业制作
  • 做网站系统的答辩ppt范文wordpress缩略图顺序
  • 辽宁省建设厅官方网站wordpress 连不到js
  • 【开题答辩全过程】以 springboot校园顺风车平台为例,包含答辩的问题和答案
  • 【2026国考省考公务员备考资料合集】免费分享
  • 网站开发最流行的语言爱心代码编程html教程
  • 建一个企业网站多少钱变色龙app制作教程
  • 一文详解RAG