CAS协议验证接口完整指南:serviceValidate与proxyValidate详解
【免费下载链接】rubycas-serverProvides single sign-on authentication for web applications, implementing the server-end of Jasig's CAS protocol.项目地址: https://gitcode.com/gh_mirrors/ru/rubycas-server
rubycas-server是一个基于 Ruby 的 CAS(Central Authentication Service)服务器端实现,为 Web 应用提供单点登录认证。它的核心职责就是响应应用端发起的CAS 协议验证请求,其中最常用的两个验证接口是serviceValidate和proxyValidate——应用把用户带来的ticket交给它们,它们回答"这个用户是谁、是否有效"。
验证接口在单点登录中的位置
先建立整体感觉。CAS 的认证流程分为 6 步:
- 用户访问受保护页面,应用将浏览器重定向到 CAS 服务器的登录页;
- 用户在 CAS 登录页输入账号密码;
- CAS 服务器向数据源(AD、LDAP、SQL 数据库等)验证凭据;
- 验证通过后,CAS 向浏览器签发一张Service Ticket(服务票据)并重定向回应用;
- 应用拿着这张 ticket 调用 serviceValidate / proxyValidate 接口,向 CAS 验证票据——这就是本文主角;
- 验证成功则用户完成登录,失败则回到登录页。
第 5 步就是验证接口的用武之地:用户与 CAS 之间的"信任凭证"(ticket)必须经服务器确认,应用才能安全地放行。票据的生命周期管理(过期、防重放)由 lib/casserver/cas.rb 统一负责。
serviceValidate:最常用的 CAS 验证接口
GET /serviceValidate是 CAS 协议 2.5.1 节定义的标准验证端点,适用于绝大多数"应用直接向 CAS 验证用户"的场景。路由定义见 lib/casserver/server.rb。
请求参数一览
| 参数 | 是否必填 | 作用 |
|---|---|---|
service | ✅ | 发起验证的应用 URL(必须与签发票据时登记的 service 一致) |
ticket | ✅ | 用户登录后拿到的服务票据(形如ST-xxxx) |
pgtUrl | ❌ | 代理回调地址;传入后 CAS 会生成 PGT 并在响应中返回 IOU |
renew | ❌ | 要求重新交互认证 |
五道关卡:CAS 如何审查一张票据
无论调用哪个验证接口,票据都要通过同一套审查逻辑(实现于 lib/casserver/cas.rb):
- 参数完整性:
service或ticket缺失 →INVALID_REQUEST; - 防重放:票据只能使用一次。验证成功后立即标记 consumed(见 lib/casserver/model/consumable.rb),第二次提交同一票据 →
INVALID_TICKET("already been used up"); - 票据类型:serviceValidate拒绝代理票据(ProxyTicket),传入 PT 会报
INVALID_TICKET; - 有效期:票据自创建起超过未使用期限(默认5 分钟,可在 config/config.example.yml 中通过
maximum_unused_service_ticket_lifetime调整)→ 过期错误; - Service 匹配:请求的
service与票据签发时绑定的应用必须完全一致,否则 →INVALID_SERVICE。
此外,两个接口都支持allowed_service_ips白名单校验(见 lib/casserver/server.rb):若配置了该选项,白名单外的 IP 调用验证接口会直接收到INVALID_REQUEST失败响应,这是防止第三方应用冒用 CAS 套取用户信息的重要防线。
响应格式:成功与失败长什么样
接口强制返回text/xml格式(视图模板为 lib/casserver/views/proxy_validate.builder)。
验证成功时,响应核心是cas:authenticationSuccess节点,其中包含:
cas:user:认证通过的用户名;cas:attributes:认证器额外提供的用户属性(如配置 SQL/LDAP 认证器时的extra_attributes,见 config/config.example.yml 的示例);cas:proxyGrantingTicket:当传入pgtUrl时返回的 PGT IOU。
验证失败时,返回cas:authenticationFailure节点,code属性携带错误码(如INVALID_TICKET、INVALID_SERVICE、INVALID_REQUEST),节点正文为可读的错误说明。HTTP 状态码也随之变化:INVALID_*类错误返回422,内部错误返回500(映射逻辑见 lib/casserver/server.rb)。
proxyValidate:支持代理链的验证接口
GET /proxyValidate(协议 2.6.1 节)是 serviceValidate 的"代理增强版",路由位于 lib/casserver/server.rb。两者的核心差异只有两点:
- 接受代理票据:proxyValidate 允许
PT-开头的 ProxyTicket 通过验证(它内部调用同一个验证函数,但打开"允许代理票据"开关,见 lib/casserver/cas.rb),并会校验代理票据确实由某个 PGT(Proxy Granting Ticket)签发; - 响应多出 proxies 节点:当票据来自代理链时,响应的
cas:authenticationSuccess内会包含cas:proxies列表,逐项列出中间代理过的服务 URL,让终端应用知道"这个身份经过了哪些代理转发"。
什么时候用 proxyValidate?当你的架构里存在"代理 CAS"(proxy CAS)层——即某个中间系统替用户向更深层的服务请求访问时,使用 proxyValidate;普通应用直接验证用户身份则用 serviceValidate 即可。配套的GET /proxy端点(用 PGT 换取代理票据)与pgtUrl参数共同构成完整的代理机制,票据生成逻辑见 lib/casserver/cas.rb。
快速上手:集成与调试要点
以下 4 个坑是集成验证接口时最常踩的,建议逐项自查:
- service 必须逐字匹配:验证请求中的
service参数要与登录重定向时的完全一致(CAS 会先对两边 URL 做清理归一化再比较,逻辑见 lib/casserver/cas.rb)。带不带的 query 参数、末尾斜杠差异都会导致INVALID_SERVICE。 - 票据一次性:浏览器刷新页面导致重复验证是典型故障源——第二次请求必然失败。应用应在拿到成功响应后立即建立本地会话,而不是反复调用验证接口。
- 注意 5 分钟时效:用户登录到应用真正调用验证接口之间不要拖太久;超时票据按过期处理。
- 配置 IP 白名单:生产环境强烈建议在 config/config.example.yml 中配置
allowed_service_ips,只允许自有应用服务器 IP 调用验证接口。
想亲眼看看行为是否符合预期?项目的 RSpec 集成测试是最好的"活文档":spec/casserver_spec.rb 完整覆盖了白名单内 IP 收到authenticationSuccess、白名单外 IP 收到 422 +INVALID_REQUEST等场景,照着它就能快速验证你的部署是否正确。
核心文件速查表
| 关注点 | 文件 |
|---|---|
| 接口路由与 IP 白名单 | lib/casserver/server.rb |
| 票据生成与五道验证关卡 | lib/casserver/cas.rb |
| XML 响应视图 | lib/casserver/views/proxy_validate.builder |
| 一次性票据逻辑 | lib/casserver/model/consumable.rb |
| 票据模型定义 | lib/casserver/model.rb |
| 票据有效期等配置 | config/config.example.yml |
| 集成测试用例 | spec/casserver_spec.rb |
小结
rubycas-server 的serviceValidate与proxyValidate是 CAS 单点登录中"信任交接"的关键端点:前者面向标准场景,用五道关卡(参数、一次性、类型、时效、service 匹配)保障票据可信;后者额外打通代理链场景,用proxies节点保留完整的代理轨迹。理解了"应用拿 ticket 来换用户名"这一本质,再配合 IP 白名单与合理的票据时效配置,你就可以放心地把这套 CAS 服务器接入自己的应用体系了。
【免费下载链接】rubycas-serverProvides single sign-on authentication for web applications, implementing the server-end of Jasig's CAS protocol.项目地址: https://gitcode.com/gh_mirrors/ru/rubycas-server
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考