前端时间学习了,cas 的sso 框架,在这里简略记录一下,拉下访客。而且这两天又在修改样式,既郁闷又痛苦,趁这个换换脑子。本篇博客记载的大多都是从网上收集加上自己总结的,并不权威。转载请注明出处。
首先是下载cas相关的资源,需要的是 cas-server-3.5.2-release.zip 里面包含 cas-server-webapp-3.5.2.war,cas-client-3.2.1-release.zip 里面包含 cas-client-core-3.2.1.jar,另在找一个jar包(casClientNew.jar),版本请随意,我用的是这两个版本,未测试其他版本。环境 jdk1.6,tomcat 6.0。
介绍我实现的功能,sso单点登录,未使用ssl,需特别说明的是,cas的安全保证很大部分依靠ssl,因此,有条件请实现。cas sso 实现的是用户验证,用户进到某个子系统的权限依然由子系统控制(我是写了一个过滤器实现的)。
接下来开始介绍步骤,至于cas 原理,网上很多介绍,我不再copy了。http://www.cnblogs.com/yonsin/archive/2009/08/29/1556423.html http://blog.csdn.net/maxgong2005/article/details/557052 请自己参考查阅。
第一步是修改cas server 服务端( cas-server-webapp-3.5.2.war),既然是单点登录一定需要验证,需要告知cas server如何验证,我采用的是cas server自己访问数据库我指定的表,验证用户名和密码。密码的加密方式是我自己实现的。我只用到了用户表的用户名和密码两个字段。cas-server 支持添加用户属性(除用户名和密码),支持验证码,等诸多功能,有兴趣请自己研究实现。
首先,配置数据源,找到WEB-INF下的deployerConfigContext.xml文件,deployerConfigContext.xml是 cas-server的重要配置文件,在里面配置数据源,请配置在第一位:
<bean id="casDataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource"> <!--SQL SERVER --> <property name="driver" value="自己选择驱动类"></property> <property name="driverUrl" value="数据库字符串"></property> <property name="user" value="用户名" /> <property name="password" value="密码" /> <property name="houseKeepingSleepTime" value="相关属性自己设置" /> <property name="prototypeCount" value="相关属性自己设置" /> <property name="maximumConnectionCount" value="相关属性自己设置" /> <property name="minimumConnectionCount" value="相关属性自己设置" /> <property name="trace" value="true" /> <property name="verbose" value="true" /> </bean>
然后配置自己实现的加密方式,当然你的加密类需要实现他的接口 org.jasig.cas.authentication.handler.PasswordEncoder:
<bean id="passwordEncoder" class="加密方式自己实现" autowire="byName"> </bean>
接下来,找到bean 为 authenticationManager 里面的一个属性 authenticationHandlers,里面list中的一个bean 类指向 HttpBasedServiceCredentialsAuthenticationHandler 中的一个属性:p:requireSecure="false" 设置成false 表示 客户端不启用 ssl。然后是HttpBasedServiceCredentialsAuthenticationHandler的下面有一个 cas 的jdbc实现bean , SearchModeSearchDatabaseAuthenticationHandler 里面添加你的数据源设置和加密方式设置。
<bean class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler" abstract="false" lazy-init="default" autowire="default"><!-- dependency-check="default" --> <property name="dataSource" ref="casDataSource" /> <property name="tableUsers" value="用户表" /> <property name="fieldUser" value="用户名" /> <property name="fieldPassword" value="密码" /> <property name="passwordEncoder" ref="passwordEncoder" /> </bean>
在到WEB-INF下的spring-configuration目录下找到文件ticketGrantingTicketCookieGenerator.xml 设置属性 p:cookieSecure="false" false表示不启用ssl。
<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator" p:cookieSecure="false" p:cookieMaxAge="-1" p:cookieName="CASTGC" p:cookiePath="/cas" />
至此服务端设置完毕,当然还有很多属性没有说,有兴趣请自己研究。
接下来是客户端的修改:首先添加相应jia包到客户端:cas-client-core-3.2.1.jar,casClientNew.jar,然后是配置过滤器,因为我的系统配置的还有webserverice等,所以cas filter的过滤路径我并没有配置/*
<!-- cas sso 验证相关 开始 --> <!--用于单点退出配置 --> <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> <filter-name>CAS Filter</filter-name> <filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class> <!--下面两个为验证地址,即cas server端的登录地址和验证地址 --> <init-param> <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name> <param-value>http://localhost:8088/cas/login</param-value> </init-param> <init-param> <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name> <param-value>http://localhost:8088/cas/serviceValidate</param-value> </init-param> <!--本工程的URL被拦截的需要验证的访问地址 --> <init-param> <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name> <param-value>localhost:8080</param-value> </init-param> </filter> <!--单点退出的过滤映射路径--> <filter-mapping> <filter-name>CAS Single Sign Out Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 系统本身登录 --> <!--<filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>--> <filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping> <listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class> </listener> <!-- cas sso 验证相关 结束-->
client获取用户名 ,而且我们假定获取的用户名是可信任的:
String username = (String) request.getSession().getAttribute(edu.yale.its.tp.cas.client.filter.CASFilter.CAS_FILTER_USER);
OK,现在为止你的系统已经可以实现单点登录了,上面的这些基本也是可以从网上随便搜下就能找到的。接下来我讲一下自己的定制。
首先是,登录页面修改,cas server的页面设置在 default_views.properties 文件里,请根据需要修改。然后说下系统的sso单点登录,有时候我们根据客户要求会集成多种登录方式,不仅仅是cas sso这个一种,因此需要你重写 edu.yale.its.tp.cas.client.filter.CASFilter,根据url选择性过滤。你重写的filter继承自CASFilter,不需过滤直接filterChain.doFilter(request, response);需要过滤的就调用super.doFilter(httprequest, response, filterChain);
然后就是关于potal,cas 框架我们一方面是想实现单点登录,一方面也希望给客户做个potal,最初我是计划potal放在casserver里面,但登录的第一次可以获取到用户信息,之后一直获取不到用户信息因此就放到了client端。cas 框架本身提供了代理模式,但按照网上配置未成功,就先自己写了一个验证方式。假如potal放的client端为A,其他为B、C。A从B、C抽取数据,B、C提供好服务类,集成同一接口配置到spring容器中。A使用URLConnection模拟调用B、C的服务时,A提供服务名作为参数传递过去,让B、C从spring容器里面取。一个是建议json传输,然后就是中文可能乱码解决:result = new String(resultJson.getBytes("iso8859-1"),"UTF-8");还有就是 CASFilter过滤时也可能存在乱码问题,请自己设置过滤器设置编码。