单点登陆框架CAS的研究
CAS作为开源的单点登陆框架已经非常的流行了。由于它对已有系统的入侵性小,支持的语言多,备受广大开发者关注;也是很多公司将之作为单点登陆的首选框架。关于CAS如何搭建的文章,网上已经非常多了,随便搜搜都一大堆。我也就不再写些重复的东西了,但是网上的东西有时候常常是不全,或版本问题搞的很多人都很迷糊。我曾经也很迷糊,如果刚接触CAS,请你继续往下看;如果你是CAS高手,请指正我说错的地方。
CAS最早是耶鲁大学开发的(CAS2.0以前的版本),后来开源出来由JASIG来继续开发(CAS2.0以后的版本)。所以,当你准备那某一片文章上手练习的时候请分清版本。个人建议还是阅读JASIG官方文档比较好。https://wiki.jasig.org/display/CASC
一个完整的单点登陆方案分两部分
CAS server
CAS server如何配置就不多说了,基本的步骤就是
1. 下载CAS server包
2. 配置Tomcat的Https访问设置
3. 部署CAS server,其实就是将.war文件拷贝到Tomcat目录下
4. 生成证书(可以买,也可以使用自签名证书,或者干脆就用http协议,那就不需要证书了)
5. 修改用户访问配置(CAS支持关系数据库,LDAP等多种数据存储)
CAS client
CAS client是部署在应用端的,因为通常单点登陆都会涉及到对已有系统的改造。所以,client端的侵入性就变的很重要。侵入性越小,越容易部署和测试。CAS框架的优点之一就在于它的client端对应用系统的侵入性比较小。对于Java的Web项目来说,你只需要在web.xml里面添加一个filter,拷贝CAS client的jar包到应用系统,然后改造登陆认证过程即可。如果CAS server用的是Https,那就还需要将证书导入到JVM的可信证书域中,通常是($JAVA_HOME/lib/security/cacerts)。
所有的一切看着都挺简单的,但实际部署中你会遇到各式各样的问题。有很多问题网上都有人解答,这里我就记录一下我遇到的一个没找到答案的问题?
现象:
当你配置完CAS server, 也部署了CAS client后。用https登陆CAS server也都没问题时,而你无论如何都无法在登陆后跳转到你期待的页面。尽管一切看起来都配置对了,证书也导了,https也配了,filter也加了。但是还是不停的抛CAS ticket validation expection, CAS server no response错误。
解决方案:
请检查你的client是否把4个filter都配置全了,并且顺序要对。
<!-- CAS SSO --> <filter> <filter-name>CAS Authentication Filter</filter-name> <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class> <init-param> <param-name>casServerLoginUrl</param-name> <param-value>https://cas-server:8443/cas/login</param-value> </init-param> <init-param> <param-name>renew</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>gateway</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://client-host:8080</param-value> </init-param> </filter> <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>https://cas-server:8443/cas/</param-value> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://client-host:8080</param-value> </init-param> <init-param> <param-name>useSession</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>redirectAfterValidation</param-name> <param-value>true</param-value> </init-param> </filter> <filter> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <filter-class> org.jasig.cas.client.util.HttpServletRequestWrapperFilter </filter-class> </filter> <filter> <filter-name>CAS Assertion Thread Local Filter</filter-name> <filter-class> org.jasig.cas.client.util.AssertionThreadLocalFilter </filter-class> </filter> <filter-mapping> <filter-name>CAS Authentication Filter</filter-name> <url-pattern>/sso/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Validation Filter</filter-name> <url-pattern>/sso/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <url-pattern>/sso/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Assertion Thread Local Filter</filter-name> <url-pattern>/sso/*</url-pattern> </filter-mapping>
官方文档特别说明这4个Filter是必须的
The correct order of the filters in web.xml is necessary:
- AuthenticationFilter
- TicketValidationFilter (whichever one is chosen)
- HttpServletRequestWrapperFilter
- AssertionThreadLocalFilter
这里我要说明一下为什么这4个filter是必须要配的。
AuthenticationFilter的作用是用于拦截SSO登陆请求的,当你提交的request符合SSO登陆规则,CAS client会通过这个filter将登陆请求转向到CAS server的登陆界面。因为这是第一步,所以它要在最上面。
TicketValidationFilter的作用是用于拦截登陆返回的跳转请求的。当CAS server确认登陆用户名密码后,会返回一个server ticket,这个ticket会由应用服务器上的CAS client再送回CAS server进行验证,用于防止仿冒攻击的。
HttpServletRequestWrapperFilter的目的是将CAS server返回的信息封装到Http request里面,这样客户端就可以用request.getRemoteUser()来获取用户名等信息了。
AssertionThreadLocalFilter的作用是用于前端程序(通常是前端脚本程序)访问,因为这个时候你无法通过request来获取信息。
所以如果这4个filter不配置正确,就会报各种错误。