概述
本文档旨在帮助第三方系统接入muvocal Auth登录系统,实现统一身份认证。接入后,用户只需在 SSO 系统登录一次,即可访问所有集成的应用系统。
系统架构
用户浏览器
│
├──> 第三方系统 (如高考志愿系统)
│ │
│ └──> SSO 登录页面
│
└──> SSO 回调处理
│
└──> SSO 令牌验证
接入步骤
1. 注册客户端应用
联系 SSO 管理员注册您的应用,提供以下信息:
- 应用名称:您的系统名称
- 回调地址:接收 SSO token 的 URL(如
https://yourdomain.com/sso_callback
)
您将获得:
client_id
– 客户端唯一标识符client_secret
– 客户端密钥(用于安全验证)
2. 配置 SSO 参数
在您的应用中添加以下配置:
# SSO 配置参数
SSO_LOGIN_URL = "https://muvocal.com/auth/login"
SSO_VERIFY_URL = "https://muvocal.com/auth/verify_token"
SSO_CLIENT_ID = "your_client_id" # 从 SSO 管理员获取
SSO_CLIENT_SECRET = "your_client_secret" # 从 SSO 管理员获取
SSO_REDIRECT_URI = "https://yourdomain.com/sso_callback" # 您的回调地址
3. 实现登录路由
在您的应用中添加登录路由:
@app.route('/login')
def sso_login():
"""重定向到 SSO 登录页面"""
return redirect(
f"{SSO_LOGIN_URL}?client_id={SSO_CLIENT_ID}&redirect_uri={SSO_REDIRECT_URI}"
)
4. 实现回调处理
添加回调路由处理 SSO 返回的 token:
@app.route('/sso_callback')
def sso_callback():
"""处理 SSO 回调"""
token = request.args.get('token')
if not token:
return "认证失败:未接收到 token", 401
try:
# 验证 token
verify_response = requests.get(
f"{SSO_VERIFY_URL}?token={token}",
headers={'Accept': 'application/json'}
)
if verify_response.status_code != 200 or not verify_response.json().get('valid'):
return "认证失败:无效的 token", 401
# 保存用户信息到 session
user_info = verify_response.json()['user']
session['user'] = {
'id': user_info['id'],
'username': user_info['username'],
'email': user_info['email']
}
# 重定向到应用首页
return redirect(url_for('home'))
except Exception as e:
app.logger.error(f"SSO回调处理失败: {str(e)}")
return "服务器内部错误", 500
5. 添加登录检查
保护需要登录的路由:
def login_required(f):
"""登录检查装饰器"""
@wraps(f)
def decorated_function(*args, **kwargs):
if 'user' not in session:
return redirect(url_for('sso_login'))
return f(*args, **kwargs)
return decorated_function
# 在需要保护的路由上使用装饰器
@app.route('/protected-page')
@login_required
def protected_page():
# 您的业务逻辑
return render_template('protected.html')
6. 实现退出功能
添加退出路由:
@app.route('/logout')
def sso_logout():
"""退出登录"""
session.pop('user', None)
# 可选:调用 SSO 全局登出
# return redirect(f"{SSO_LOGOUT_URL}?redirect_uri={url_for('home')}")
return redirect(url_for('home'))
认证流程说明
登录流程
- 用户访问您的系统
- 点击登录按钮 → 重定向到 SSO 登录页面
- 用户在 SSO 系统输入凭据登录
- SSO 验证凭据,生成 JWT token
- SSO 重定向回您的回调地址(附带 token)
- 您的系统验证 token 并建立本地会话
- 用户登录成功,访问您的系统
登出流程
- 用户点击退出按钮
- 您的系统清除本地会话
- (可选)重定向到 SSO 全局登出页面
安全配置要求
1. 会话密钥
在您的 Flask 应用中设置强密钥:
import os
app = Flask(__name__)
app.secret_key = os.environ.get('FLASK_SECRET_KEY', os.urandom(24))
2. HTTPS 要求
- 生产环境必须启用 HTTPS
- 所有回调 URL 必须使用 HTTPS
- 设置安全 Cookie:
app.config.update(
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Lax'
)
3. 令牌验证
- 验证 token 有效期(默认 30 分钟)
- 检查 token 签名
- 处理可能的错误情况:
- Token 过期
- 无效签名
- 用户不存在
用户信息结构
SSO 系统返回的用户信息包含以下字段:
{
"id": 123,
"username": "user123",
"email": "user@example.com"
}
错误处理
常见错误及解决方案
错误代码 | 描述 | 解决方案 |
---|---|---|
401 | 无效 token | 重新登录 |
400 | 缺少参数 | 检查回调 URL |
500 | 服务器错误 | 检查日志并重试 |
403 | 访问被拒绝 | 检查客户端权限 |
日志记录建议
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('app.log'),
logging.StreamHandler()
]
)
最佳实践
- 会话管理:
- 设置会话超时(建议 8 小时)
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=8)
- 错误页面:
- 自定义 401、404、500 错误页面
@app.errorhandler(401)
def unauthorized(e):
return render_template('401.html'), 401
- 性能优化:
- 缓存用户信息(避免每次请求都验证 token)
- 使用连接池管理 HTTP 请求
- 用户界面:
- 添加登录状态显示
- 提供清晰的登录/退出入口
- 显示用户名和退出选项
示例代码
完整接入示例
from flask import Flask, session, redirect, url_for, request
import requests
from datetime import timedelta
import os
app = Flask(__name__)
# 配置强密钥
app.secret_key = os.environ.get('FLASK_SECRET_KEY', os.urandom(24))
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=8)
# SSO 配置
SSO_LOGIN_URL = "https://muvocal.com/auth/login"
SSO_VERIFY_URL = "https://muvocal.com/auth/verify_token"
SSO_CLIENT_ID = "your_client_id"
SSO_REDIRECT_URI = "https://youradmin.com/sso_callback"
# 登录检查装饰器
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if 'user' not in session:
return redirect(url_for('sso_login'))
return f(*args, **kwargs)
return decorated_function
@app.route('/login')
def sso_login():
"""重定向到 SSO 登录页面"""
return redirect(f"{SSO_LOGIN_URL}?client_id={SSO_CLIENT_ID}&redirect_uri={SSO_REDIRECT_URI}")
@app.route('/sso_callback')
def sso_callback():
"""处理 SSO 回调"""
token = request.args.get('token')
if not token:
return render_template('error.html', message="未接收到 token"), 401
try:
# 验证 token
response = requests.get(f"{SSO_VERIFY_URL}?token={token}")
data = response.json()
if not data.get('valid'):
return render_template('error.html', message="无效 token"), 401
# 保存用户信息
session.permanent = True
session['user'] = data['user']
return redirect(url_for('home'))
except Exception as e:
app.logger.error(f"SSO回调错误: {str(e)}")
return render_template('error.html', message="认证服务不可用"), 500
@app.route('/logout')
def sso_logout():
"""退出登录"""
session.pop('user', None)
return redirect(url_for('home'))
@app.route('/')
def home():
"""首页"""
return render_template('index.html', user=session.get('user'))
@app.route('/dashboard')
@login_required
def dashboard():
"""需要登录的仪表盘"""
return render_template('dashboard.html', user=session['user'])
技术支持
如需帮助,请联系:
- 文档中心:穆音文档中心
版本历史
版本 | 日期 | 描述 |
---|---|---|
1.0 | 2023-10-15 | 初始版本 |
1.1 | 2023-11-01 | 增加错误处理指南 |
1.2 | 2025-5-20 | 更新安全配置要求 |
通过遵循本文档,您的系统可以快速、安全地接入 SSO 单点登录系统,为用户提供无缝的登录体验。
发表回复