rubycas-server架构剖析:Sinatra+ActiveRecord如何优雅实现单点认证服务端
rubycas-server架构剖析SinatraActiveRecord如何优雅实现单点认证服务端【免费下载链接】rubycas-serverProvides single sign-on authentication for web applications, implementing the server-end of Jasigs CAS protocol.项目地址: https://gitcode.com/gh_mirrors/ru/rubycas-serverrubycas-server 是一个基于 Ruby 编写的 CAS 单点登录SSO认证服务端用极简的 Sinatra 路由 ActiveRecord 票据模型完整实现了 Jasig CAS 协议的服务端逻辑。本文将带你快速看懂它的分层架构从登录路由、四类票据的数据库模型到可插拔的认证器体系理解它是如何优雅地完成一次登录、处处通行的。1 分钟认识 CAS 单点登录单点登录的核心体验是在一个地方登录一次之后访问所有接入系统都不用再输密码。CASCentral Authentication Service协议把这件事拆成三个角色CAS 服务端即本项目负责验证用户身份、签发票据服务应用Service用户实际访问的业务系统票据Ticket服务端发给用户的一次性通行证接入流程大致是用户访问受保护应用应用把用户重定向到 CAS 服务端/login用户输入账号密码服务端验证通过后签发TGT会话凭证服务端为该应用生成一次性ST服务票据重定向回应用并带上 ST应用后端拿 ST 请求/serviceValidate校验成功后即放行用户之后再访问其他接入应用浏览器带着 TGT 访问/login时直接免密跳转rubycas-server 的全部代码就是围绕这条流程展开的。整体架构Sinatra 与 ActiveRecord 各司其职整个项目的入口只有十几行见 config.ru挂上 Rack 中间件后直接把CASServer::Server交给 Rack 运行。真正的骨架由四个层次组成HTTP 请求 │ ▼ ┌─────────────────────────────────────────┐ │ 路由层 lib/casserver/server.rb │ ← Sinatra 定义 CAS 协议端点 ├─────────────────────────────────────────┤ │ 协议逻辑层 lib/casserver/cas.rb │ ← 票据生成 / 校验的核心方法 ├─────────────────────────────────────────┤ │ 模型层 lib/casserver/model.rb │ ← ActiveRecord 持久化票据 ├─────────────────────────────────────────┤ │ 认证层 lib/casserver/authenticators/ │ ← 可插拔的身份验证实现 └─────────────────────────────────────────┘层次位置职责路由层lib/casserver/server.rb定义/login、/logout、/serviceValidate等 CAS 端点协议逻辑层lib/casserver/cas.rb票据的生成、校验、过期判断模型层lib/casserver/model.rbLT/TGT/ST/PT/PGT 五类票据的数据库模型认证层lib/casserver/authenticators/SQL、LDAP、Google、OpenID 等身份验证器配置config/config.example.yml数据库、认证器、端口、日志等全部配置这种薄路由 厚模块的写法正是 Sinatra 相对 Rails 的特色没有庞大的框架约定所有行为一目了然。路由层一个文件读完 CAS 协议端点CASServer::Server 继承自CASServer::Base一个注册了 i18n 多语言支持的 Sinatra::Base见 lib/casserver/base.rb并把CASServer::CAS协议模块include进来。代码里的# 2.1、# 3.2等注释对应 CAS 协议规范章节号方便逐条对照。核心路由与 CAS 协议端点的映射GET /loginL284检查浏览器中的 TGT Cookie——若已登录且非 renew 请求直接签发 ST 并 303 重定向这就是免密单点登录的实现处POST /loginL387依次尝试配置中的每个认证器成功后写入tgtCookie 并生成 STGET /logoutL508删除 Cookie并在一个数据库事务里级联删除 TGT 及其名下所有 ST、PGTGET /serviceValidateL630与/proxyValidateL669返回 XML 校验结果供应用后端调用GET /proxyL716为代理链场景签发 PT 票据POST /loginTicketL586为远程自定义登录页单独发放 LT另外还有一个安全细节校验端点会先用 ip_allowed? 判断请求 IP 是否在allowed_service_ips白名单中防止任意外部系统伪造校验请求。模型层用 ActiveRecord 优雅管理 5 种票据CAS 协议涉及五种票据rubycas-server 用五张 ActiveRecord 模型一一对应lib/casserver/model.rb模型前缀数据库表作用LoginTicketLT-casserver_lt防表单重复提交一次性消费TicketGrantingTicketTGT-casserver_tgt用户 SSO 会话主凭证存于 CookieServiceTicketST-casserver_st一次性服务票据绑定某个 serviceProxyTicketPT-casserver_st代理链中跨服务传递的票据ProxyGrantingTicketPGT-casserver_pgt允许应用为后端系统申请代理票据模型之间通过外键形成清晰的层级关系TGT 一对多持有 STgranted_by_tgt_idPGT 归属于 STservice_ticket_idPT 又归属于 PGT——与协议中票据的签发链条完全一致。两个 Mixin 让模型设计格外干净Consumable提供consume!方法把consumed字段置为当前时间。ST 和 LT 都是一次性票据校验时先查consumed?即可防重放Ticket提供类级cleanup(max_lifetime)按创建时间批量销毁过期票据建表结构由 db/migrate/001_create_initial_structure.rb 创建db/migrate/002_add_indexes_for_performance.rb 再补上性能索引。更省心的是服务端启动时会自动执行迁移init_database!无需手动维护 schema。协议逻辑层票据的生成与校验CASServer::CAS 是纯逻辑模块不含任何路由核心方法一览generate_login_ticketL13LT- 随机串记下来源主机generate_ticket_granting_ticketL31认证成功后签发 TGT可携带extra_attributes认证器附带的用户属性generate_service_ticketL45为指定 service 生成 ST 并关联 TGTvalidate_login_ticketL118检查存在性、是否已消费、是否超过 5 分钟未使用validate_service_ticketL167依次校验已消费、类型、过期、service 是否匹配失败会返回带INVALID_TICKET/INVALID_SERVICE等错误码的Error对象把生成和校验从路由中抽离成独立模块意味着自定义视图、换模板引擎甚至重写路由都不必碰协议核心——这是本项目最值得借鉴的结构决策。认证层可插拔的身份验证器用户是谁与票据怎么发完全解耦。所有认证器都继承 CASServer::Authenticators::Base约定三个钩子self.setup(options)服务启动时调用一次例如建立 LDAP/数据库连接configure(options)每次登录尝试前初始化实例validate(credentials)必须实现的抽象方法返回布尔值即可内置认证器覆盖了绝大多数场景认证器适用场景SQL用户表在 MySQL/PostgreSQL 等数据库SQLBcrypt / SQLMD5密码经 bcrypt / MD5 加密存储LDAP / ActiveDirectoryLDAP企业 Active DirectoryGoogleGoogle 账户OpenIDOpenID 2.0ClientCertificate客户端证书关键在启动逻辑 init_authenticators!配置文件里的authenticator列表按顺序实例化且支持多个认证器排队——POST /login时会依次尝试第一个验证成功即终止。想接入自己的身份源写一个继承Base的小类、在配置里声明class即可甚至可以写source指向任意 Ruby 文件加载L198-L204无需修改框架代码。启动流程与关键配置服务启动是一条清晰的初始化链configure 块load_config_file读 YAML 配置缺文件时还会交互式复制示例配置init_logger!主日志与 ActiveRecord 日志分流init_database!连接数据库并自动跑迁移init_authenticators!实例化并 setup 全部认证器默认值内置在代码里L26-L33LT 与 ST 未使用有效期 5 分钟、会话最长 2 天——与 CAS 协议规范的建议值一致。快速跑起来的步骤以 MySQL 为例git clone https://gitcode.com/gh_mirrors/ru/rubycas-server cd rubycas-server cp config/config.example.yml config.yml # 编辑 config.yml数据库、认证器、端口(可用 8888 免 SSL) # 在 Gemfile 中加入数据库驱动如 gem mysql2 bundle install bundle exec rubycas-server -c config.yml生产部署可改用 Unicorn 等 Rack handler配置文件在 config/unicorn.rb测试套件覆盖核心模块见 spec/ 目录。关键源码文件清单文件说明config.ruRack 应用入口lib/casserver/server.rb路由、配置加载、启动逻辑lib/casserver/cas.rb票据生成与校验协议核心lib/casserver/model.rb五类票据的 ActiveRecord 模型lib/casserver/authenticators/base.rb认证器抽象基类db/migrate/数据库结构迁移locales/12 种语言的界面文案含 zh.ymlpublic/themes/登录页主题样式总结值得借鉴的三个设计分层清晰Sinatra 只写路由协议逻辑在CAS模块持久化在模型层身份验证在认证器层——每一层都能独立替换票据即数据把协议中的 LT/TGT/ST/PT/PGT 全部落库成 ActiveRecord 模型用 Mixin 实现一次性消费和过期清理防重放逻辑仅几行认证器可插拔setup / configure / validate三钩子 配置驱动的多认证器排队扩展身份源几乎零侵入对于想自研或理解单点登录服务端的同学rubycas-server 是一个小而完整的绝佳范本不到千行核心代码读得完、改得动、上得了生产。【免费下载链接】rubycas-serverProvides single sign-on authentication for web applications, implementing the server-end of Jasigs CAS protocol.项目地址: https://gitcode.com/gh_mirrors/ru/rubycas-server创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考