博主最近使用CAS做单点登录 , 测试demo中, 碰到如下问题, 解决过程曲折, 现分享如下:
问题一: CAS单点登出功能 bug 描述:
问题描述:
开发环境下, idea中tomcat插件运行CAS Client_1和Client_2两个项目, 将CAS Server部署在Linux系统上的tomcat中:
1. 当访问Client_1时, 进行登录, 此时可直接访问Client_2, 无需登录,即单点登录功能正常;
2. 当访问单点登出地址后, 页面显示登出成功, 此时再次访问Client_1, 被要求再次登录, 但是访问Client_2却无需登录, 可以直接访问;
Client_1关键配置信息(web.xml中) (Client_1除端口号外 相同):
<!-- ======================== 单点登录开始 ======================== -->
<!--TODO 单点登出-->
<!-- 单点登出过滤器 用于单点退出,该过滤器用于实现单点登出功能,可选配置 -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- 该过滤器用于实现单点登出功能,可选配置。 -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--TODO 单点登录-->
<!-- 该过滤器负责用户的认证工作,必须启用它 -->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://192.168.25.129:8082/cas/login</param-value>
<!--这里的server是服务端的IP -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:9018</param-value>
<!--当前系统的客户端的端口号-->
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://192.168.25.129:8082/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:9018</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
此时考虑: 理想情况下整个登陆登出过程:
1. 访问Client_1, 要求进行登录, 于是基于Client_1跳转到登录页面, 并向 casServer发出认证请求, 此时为认证操作, 服务器判断账号密码后返回ticket;
2. 此时访问Client_2, 因为持有ticket, 所以casServer直接验证ticket有效, 允许访问, 且再次访问时, 只要ticket不变, 是不需要经过casServer的;
3. 登出: 访问casServer的登出链接 /cas/logout, 要求登出, casServer销毁认证信息, 并通知认证过的系统, 要求销毁该浏览器客户端的ticket许可,;
4. 登出后, Client_1 或 Client_2 再次登录时, 因为ticket失效, 则被要求再次登录, 因为回到步骤1 阶段;
问题分析:
1. 目前的问题是, 第一次认证的系统 Client_1 可以被有效登出, 其余持ticket去验证的系统 Client_2 , 未被有效登出;
2. 故问题出在: casServer未能通知后续持ticket进行验证登录的系统 Client_2 去销毁该浏览器的认证信息, 导致Client_2可以继续被该浏览器持过期ticket访问 ;
问题原因:
casServer登出时, 无法通知ip设置为: localhost 的验证客户端 (认证客户端(即跳转登陆的客户端)可以识别)
问题解决:
将客户端ip设置为本机IPV4地址, 即windows系统中输入ipconfig 或linux系统中输入 ifconfig, 获取ipv4地址, 且保证改地址能被casServer所在linux系统ping通;
关键配置如下:
错误:
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:9018</param-value>
<!--当前系统的客户端的端口号-->
</init-param>
正确如下(共两处, 认证和验证过滤器均需要):
<init-param>
<param-name>serverName</param-name>
<param-value>http://192.168.25.1:9018</param-value>
<!--当前系统的客户端的端口号-->
</init-param>
后续:其实可以只修改验证过滤器的配置, 因为认证过滤器配置为localhost是可以正确识别的;
正确的完整配置 (web.xml中) 供参考: (和spring整合时, 配置bean的属性即可, 原理相同)
<!-- ======================== 单点登录开始 ======================== -->
<!--TODO 单点登出-->
<!-- 单点登出过滤器 用于单点退出,该过滤器用于实现单点登出功能,可选配置 -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- 该过滤器用于实现单点登出功能,可选配置。 -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--TODO 单点登录-->
<!-- 该过滤器负责用户的认证工作,必须启用它 -->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://192.168.25.129:8082/cas/login</param-value>
<!--这里的server是服务端的IP -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://192.168.25.1:9019</param-value>
<!--当前系统的客户端的端口号-->
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://192.168.25.129:8082/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://192.168.25.1:9019</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
问题二:cas jar包cas-client-core由3.3.3切换到3.4.1时, 报错:
严重: Exception starting filter CAS Single Sign Out Filter
java.lang.IllegalArgumentException: casServerUrlPrefix cannot be null.
原因:
3.4.1版本(其它版本未实测, 可参考)需要手动配置登出链接的前缀, 故单点登出过滤器的配置中增加相关属性即可:
解决办法:
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://cas服务器的ip加端口号/cas</param-value>
</init-param>
</filter>
----------------------------------------------------------------------------------------结束---------------------------------------------------------------------------------------
转载请标明出处: 划船一哥