必须走通HTTPS链路,用keytool生成含域名CN的自签名证书→导入客户端JVM cacerts→服务端配置HTTPS Connector→对接数据库并释放用户属性→客户端严格配置CasAuthenticationFilter顺序与service URL→启用双向登出清理机制。

Java CAS 通关演练不是背配置,而是按真实链路跑通一次:证书→服务端→客户端→属性传递→登出闭环。关键在每一步验证点是否通过,而不是堆参数。
证书必须走通 HTTPS 链路
CAS 默认强制 HTTPS,跳过证书会卡在重定向或报 SSLHandshakeException。哪怕本地开发,也得用域名+自签名证书:
- 用 keytool 生成 keystore,alias 和 CN 必须填域名(如 sso.example.com),不能填 IP 或 localhost
- 修改 hosts 文件映射该域名到 127.0.0.1,确保浏览器访问 https://sso.example.com:8443/cas/login 能打开登录页
- 把导出的 .crt 文件导入客户端 JVM 的 cacerts(路径通常是 $JAVA_HOME/jre/lib/security/cacerts),密码默认 changeit
- Tomcat server.xml 中 Connector 配置需指向该 keystore,并启用 scheme="https"、secure="true"
CAS Server 要能查库、能返回属性
默认 casuser/Mellon 只用于测试,生产必须对接数据库并透出用户字段:
- 在 application.properties 或 cas.properties 中配置 JDBC 认证,例如:
cas.authn.jdbc.query[0].sql=select * from sys_user where username=?
cas.authn.jdbc.query[0].fieldPassword=password
cas.authn.jdbc.query[0].driverClass=com.mysql.cj.jdbc.Driver - 启用属性释放策略,比如在 service registry 中为客户端服务配置:
attributeReleasePolicy: { "cn": "username", "mail": "email" } - 重启后访问 https://sso.example.com:8443/cas/login,用数据库里的账号密码登录,确认跳转后 URL 带 ticket 参数
CAS Client 过滤器顺序和回调地址必须严丝合缝
90% 的“登了还跳登录页”问题出在这两处:
立即学习“Java免费学习笔记(深入)”;
- CasAuthenticationFilter 必须插在 UsernamePasswordAuthenticationFilter 之前,Spring Security 配置中写:
.addFilterBefore(casFilter(), UsernamePasswordAuthenticationFilter.class) - service URL 必须和客户端实际接收回调的路径完全一致,协议、域名、端口、路径一个字符都不能错,例如:
service: https://app.example.com/login/cas(不是 /cas/login,也不是前端路由) - 开启 DEBUG 日志,重点看 CasAuthenticationFilter 是否执行、是否解析出 ticket、是否调用 validator
- 校验器推荐用 Cas30ServiceTicketValidator,兼容性更好,尤其对接 CAS 5+/6+
登出要双向清理,否则 Token 冲突
单点登出(SLO)不是可选项,是避免 Session 污染的刚需:
- Server 端启用 SLO:在 cas.properties 中设 cas.logout.type=BACK_CHANNEL 或 FRONT_CHANNEL
- Client 端加 SingleSignOutFilter,且放在最前面:
registry.addFilter(singleSignOutFilter(), SecurityWebFiltersOrder.HTTP_BASIC)(WebFlux)或
addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class)(MVC) - 登出时访问 /cas/logout,确认 Server 返回 200,Client 的 HttpSession 被销毁,后续请求不再携带 JSESSIONID
- 若用集群部署,TGT 存 Redis,需配置 cas.tgt.redis.enabled=true 并指定连接池


















