如何为客户Web门户创建简单安全的SSO/身份认证接入API?
好的,结合你描述的场景——客户已经掌握其用户的邮箱,要从自有网站无缝跳转到你们的托管门户实现SSO,我来给你一套简单又安全的实现方案,核心是基于签名验证的一次性临时登录凭证,既容易落地,又能有效防范伪造请求:
整体流程概述
- 客户网站在用户触发跳转操作时,通过后端生成带签名的请求,调用你的SSO API获取临时登录令牌
- 你的API验证签名合法性后,返回短期有效的一次性令牌
- 客户网站将用户重定向到你的门户,并携带该令牌
- 你的门户验证令牌有效性后,直接为用户创建会话,完成登录
具体实现步骤
1. 预配置:共享密钥(核心安全基础)
- 你和客户之间预先约定一个强随机共享密钥(建议32位以上的随机字符串,比如用
openssl rand -hex 16生成) - 这个密钥必须严格保密,仅在双方后端服务器存储,绝对不能暴露给前端代码或第三方
- 建议定期轮换密钥(比如每3个月),轮换时提前同步给客户
2. 设计SSO令牌获取API(后端接口)
接口采用POST /api/sso/get-token,请求体为JSON格式:
{ "user_email": "user@client-domain.com", "timestamp": 1700000000, "signature": "a1b2c3d4e5f6..." }
参数说明:
user_email:客户提供的目标用户邮箱(需是客户管理的合法邮箱)timestamp:当前Unix时间戳(秒级),用于防止重放攻击,建议设置5分钟内有效signature:签名值,生成规则:将user_email + | + timestamp + | + 共享密钥拼接后,用HMAC-SHA256加密,再转成十六进制字符串(用|做分隔符避免参数拼接混淆)
API验证逻辑:
- 首先检查
timestamp是否在当前时间±5分钟范围内,超出则直接拒绝请求 - 按照相同规则重新计算签名,与请求中的
signature对比,不一致则拒绝 - 验证该邮箱是否属于该客户的合法用户(如果你的系统已存储客户用户数据,直接查询;若未存储,可要求客户保证邮箱合法性,或额外调用客户的用户验证接口)
- 生成一个短期有效(5分钟以内)的一次性JWT令牌,令牌中仅包含
user_email和exp(过期时间)两个字段,用你的私钥(或共享密钥)进行签名 - 返回令牌给客户后端:
{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2VtYWlsIjoidXNlckBjbGllbnQtZG9tYWluLmNvbSIsImV4cCI6MTcwMDAwMDMwMH0.SxXZ8kQZ9eR..." }
3. 客户网站端的跳转逻辑
当用户点击“进入托管门户”按钮时:
- 前端调用客户自身的后端接口(绝对不能在前端处理签名逻辑)
- 客户后端生成
user_email、timestamp,计算signature,调用你的SSO API获取令牌 - 拿到令牌后,将用户重定向到你的门户登录页,示例URL:
GET /portal/login?sso_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
注:如果担心URL泄露令牌,也可以用POST表单提交令牌,但GET方式更简单适配跳转场景
4. 你的门户端的登录验证逻辑
门户的登录页(或专门的SSO回调页)处理流程:
- 从URL参数中提取
sso_token - 验证JWT令牌的签名有效性,检查是否过期
- 解析令牌中的
user_email,查询你的系统中是否存在该用户 - 若用户存在,直接创建用户会话(比如设置HttpOnly、Secure属性的Cookie),跳转到门户首页
- 若用户不存在:根据业务逻辑处理——可以自动创建用户(需提前和客户约定),或返回错误提示客户同步用户数据
关键安全防护措施(必须落实)
- 禁止前端处理签名:共享密钥仅在双方后端存储,前端永远不能接触密钥,避免泄露风险
- 短期有效令牌:令牌有效期严格控制在5分钟以内,即使泄露也无法长时间滥用
- 重放攻击防护:除了
timestamp时效限制,还可以维护一个10分钟内的签名黑名单,用过的签名直接拒绝 - 强制HTTPS:所有API请求和跳转必须使用HTTPS,防止数据被窃听或篡改
- JWT安全设置:不要在令牌中存放敏感信息,仅保留必要的用户标识;使用强加密算法(推荐RS256,用公钥私钥对替代共享密钥,安全性更高);设置
HttpOnly、Secure属性的Cookie存储会话 - 日志监控:记录所有SSO请求的日志,包括
user_email、timestamp、请求IP、签名结果等,方便排查异常
备选简化方案(针对技术能力有限的客户)
如果客户不想处理复杂的签名逻辑,也可以采用一次性登录链接方案:
- 客户后端调用你的API(需通过IP白名单+API密钥验证请求合法性),传入
user_email - 你的API生成一个短期有效的唯一token,拼接成登录链接(比如
/portal/sso-login?token=abc123)返回给客户 - 客户网站将用户重定向到该链接,你的门户验证token后直接为用户创建会话
注:此方案的核心是确保客户调用你API的请求合法性,必须通过IP白名单或API密钥验证,否则任何人都可以生成登录链接
内容的提问来源于stack exchange,提问作者Chris




