NS 票据(NS Ticket)¶
NS 票据是产品以 ns 模式接入套件时,NereidSphere 与产品后端之间安全
传递"已认证身份"的一种短期、一次性密封凭证。它只在用户从门户跳转进入
产品的那一次重定向中出现,用于让产品在不接触 NereidSphere
会话、也不直接对接身份服务的情况下,安全地获知
"你是谁、属于哪些租户与角色"。
为什么需要票据¶
产品(NereidLink、NereidForge、NereidHorizon)独立部署在各自域名下,存在 两个客观约束:
- 浏览器跳转到产品域名时,只携带该域名的 Cookie,读不到 NereidSphere 的 会话 Cookie;产品也不被允许直接读取或校验 NS 会话。
- 浏览器重定向这条"前端信道"会经过浏览器历史、代理/入口访问日志、Referer 头等位置,不能承载真实身份数据。
因此浏览器跳转时只携带一串不透明的票据密文;用户的真实身份信息不在浏览器 跳转链路中传递,只在产品后端 ↔ NereidSphere 后端的服务器间请求中 交换。
交接流程¶
- 用户已在 NereidSphere 登录,点击门户产品卡片,打开
GET /auth/enter/{product}。 - NS 校验会话与产品授权(默认拒绝策略:需有该产品的分配分组,或持有套件
admin角色),随后签发票据并以302跳转到产品回调地址https://产品/auth/ns-callback?ticket=…。 - 产品后端立刻携带自身的服务端凭据(
X-NS-Client-Id/X-NS-Client-Secret)调用POST /api/v1/auth/ticket/verify交换票据。 - NS 校验通过后返回身份快照(
sub、用户名、邮箱、套件角色、产品分组), 产品据此建立自己的本地会话。票据随即作废。
整个过程与 CAS 的 Service Ticket、OAuth2 授权码"前端信道拿引用、后端信道 拿断言"以及 SAML Artifact Binding 是同一类成熟思路,并非自定义密码协议。
票据的内容与形态¶
票据是一个用服务端 32 字节密钥做 AES-256-GCM 认证加密的信封,包含:
- 用途标记
kind(与会话 Cookie、登录流程 Cookie 隔离,密文不能跨用途 重放); - 唯一编号
jti、目标产品aud、身份快照、产品内深链to、签发与过期 时间。
浏览器看到的只是一串不透明密文。票据是无状态的:信封自带全部信息, 任何 NS 副本都能验证,出票不需要写数据库。
安全性¶
- 防伪造、防篡改:AES-256-GCM 同时保证机密性与完整性,改动一个比特即 解密失败;密封密钥只存在于 NS 服务端,产品和浏览器都不持有,无法自行 签发票据。
- 防重放:每张票有随机
jti,消费时以原子操作(多副本下为共享 Valkey 的SET NX PX)占用,第二次交换即被拒绝(TICKET_NOT_FOUND)。票据 存储不可用时失败闭合(503TICKET_STORE_UNAVAILABLE),宁可登录 失败也不冒放行两次的风险。 - 防盗用:有效期仅 30 秒、只能使用一次,合法回调通常在 1 秒内完成 消费;全程 HTTPS;票据不经过浏览器 JavaScript,也不写入本地存储。即使票 据泄露到日志,被翻出时也早已过期并被消费。
- 产品隔离(受众绑定):一张票只开给一个产品(
aud)。产品只能用自己 的密钥换取开给自己的票,跨产品使用返回TICKET_AUDIENCE,且票据在受众 校验失败时同样作废,防止拿一张票逐个产品试探。每个产品的共享密钥独立, 比较使用恒定时间算法;单个产品被攻破,既不能伪造票据,也碰不到其他产品的 票。 - 防开放重定向:登录后跳转与产品回调地址只接受配置内的精确来源,产品内 深链只允许相对路径。
- 撤销及时:票据里的角色/分组是出票瞬间的快照,30 秒生命周期使权限变更 的窗口可以忽略;产品在每次 SSO 登录时按最新分组重新对账成员关系。
当前边界与后续加固方向¶
- 密封密钥目前为静态密钥,自动化密钥轮换(
kid+ 新旧密钥并存)尚未实现。 - 服务端换票接口当前依赖 HTTPS 与每产品共享密钥;内部链路可进一步启用 mTLS 作为纵深防御。
- 票据目前经重定向 URL 传递(与 CAS/授权码的通行做法一致);如未来需要更严 基线,可改为 POST 表单自动提交,把票据移入请求体,协议形状不变。
相关的 OIDC 授权码 + PKCE 流程发生在 NereidSphere 与 NereidIdentity 之间, 属于通用标准规程;NS 票据是产品接入这一层的套件机制。另见 单点登录(SSO)与网关。