单点登录(Single Sign On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
CAS(Central Authentication Service)是一款不错的针对 Web 应用的单点登录框架,本文介绍了 CAS 的原理、协议、在 Tomcat 中的配置和使用,研究如何采用 CAS 实现轻量级单点登录解决方案。
CAS 是 Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。CAS 具有以下特点:
开源的企业级单点登录解决方案。
CAS Server 为需要独立部署的 Web 应用。
CAS Client 支持非常多的客户端(这里指单点登录系统中的各个 Web 应用),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。
CAS Server
CAS Server 负责完成对用户的认证工作, CAS Server 需要独立部署,有不止一种 CAS Server 的实现, Yale CAS Server 和 ESUP CAS Server 都是很不错的选择。
CAS Server 会处理用户名 / 密码等凭证 (Credentials) ,它可能会到数据库检索一条用户帐号信息,也可能在 XML 文件中检索用户密码,对这种方式, CAS 均提供一种灵活但同一的接口 / 实现分离的方式, CAS 究竟是用何种认证方式,跟 CAS 协议是分离的,也就是,这个认证的实现细节可以自己定制和扩展。
CAS Client
CAS Client 负责部署在客户端(注意,我是指 Web 应用),原则上, CAS Client 的部署意味着,当有对本地 Web 应用的受保护资源的访问请求,并且需要对请求方进行身份认证, Web 应用不再接受任何的用户名密码等类似的 Credentials ,而是重定向到 CAS Server 进行认证。
目前, CAS Client 支持(某些在完善中)非常多的客户端,包括 Java 、 .Net 、 ISAPI 、 Php 、 Perl 、 uPortal 、 Acegi 、 Ruby 、 VBScript 等客户端,几乎可以这样说, CAS 协议能够适合任何语言编写的客户端应用。
从CAS v1到现在的CAS v3,整个协议的基础思想都是基于票据方式。
CAS v1非常原始,传送一个用户名”yes\ndavid.turing”的方式,CAS v2开始使用了XML规范,大大增强了可扩展性,CAS v3开始使用AOP技术,让Spring爱好者可以轻松配置CAS Server到现有的应用环境中。
CAS是通过TGT(Ticket Granting Ticket)来获取ST(Service Ticket),通过ST来访问服务,而CAS也有对应TGT,ST的实体,而且他们在保护TGT的方法上虽然有所区别,但是,最终都可以实现这样一个目的——免去多次登录的麻烦。
TGT + S = ST ?(可能是这样)
下面,我们看看CAS的基本协议框架:
CAS基础模式
上图是一个最基础的 CAS 协议, CAS Client 以 Filter 方式保护 Web 应用的受保护资源,过滤从客户端过来的每一个 Web 请求,同时, CAS Client 会分析 HTTP 请求中是否包请求 Service Ticket(上图中的 Ticket) ,如果没有,则说明该用户是没有经过认证的,于是, CAS Client 会重定向用户请求到 CAS Server ( Step 2 )。 Step 3 是用户认证过程,如果用户提供了正确的 Credentials , CAS Server 会产生一个随机的 Service Ticket ,然后,缓存该 Ticket ,并且重定向用户到 CAS Client (附带刚才产生的 Service Ticket ), Service Ticket 是不可以伪造的,最后, Step 5 和 Step6 是 CAS Client 和 CAS Server 之间完成了一个对用户的身份核实,用 Ticket 查到 Username ,因为 Ticket 是 CAS Server 产生的,因此,所以 CAS Server 的判断是毋庸置疑的。
该协议完成了一个很简单的任务,就是 User(david.turing) 打开 IE ,直接访问 clientweb 应用,它被立即重定向到 CAS Server 进行认证, User 可能感觉到浏览器在 clientweb 和 casserver 之间重定向,但 User 是看不到, CAS Client 和 CAS Server 相互间的 Service Ticket 核实 (Validation) 过程。当 CAS Server 告知 CAS Client 用户 Service Ticket 对应确凿身份, CAS Client 才会对当前 Request 的用户进行服务。
再看两个比较有用的图,这个是从网上找到的,一个是CAS浏览器请求序列图,另一个是CAS服务器端登陆流程图(参考http://hi.baidu.com/dianjinglong/blog/item/f74f353156d390a15fdf0e43.html)
CAS浏览器请求序列图
CAS服务器端登陆流程图
Server端主要是需要安装Server的WAR包,并运行起来。由于 Client 与 CAS Server 之间的交互采用 Https 协议,因此部署 CAS Server 的服务器还需要支持 SSL 协议。当 SSL 配置成功过后,(也可以不使用SSL协议,而使用普通方式)像普通 Web 应用一样将 CAS Server 部署在服务器上就能正常运行了,不过,在真正使用之前,还需要扩展验证用户的接口。
生成key的步骤省略,参看这里,介绍的很详细。之后配置tomcat的server.xml文件,增加如下配置,将JDK的cacerts配置到tomcat的信任库中:
修改%TOMCAT_HOME%/conf/server.xml
去掉下面SSL HTTP那个注释,修改为如下:
Xml代码
<Connector port="8443" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystoreFile="/conf/tomcat.keystore" keystorePass="123456" />
keystoreFile 是tomcat.keystore放置的位置,keystorePass是前面生成tomcat.keystore所设置的密码(123456)
也可取消CAS的HTTPS登录,需要设置几个地方。可以参考这里。
概括来说就是查找Secure字符,找到两个设置的地方,把true改成false;
修改deployerConfigContext.xml <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient" />
添加p:requireSecure="false"
客户端可能也需要进行修改。
我这里的Cas-server的版本是 3.4.2.1
目前,部署下载的server中module里的war包到tomcat中,启动tomcat,然后访问:https://localhost:8443/cas ,如果能出现正常的 CAS 登录页面,则说明 CAS Server 已经部署成功。
虽然 CAS Server 已经部署成功,但这只是一个缺省的实现,在默认的server界面,只要输入用户名和密码相同,就可以登录。当然,在实际使用的时候,这样做肯定是不行的,还需要根据实际概况做扩展和定制,最主要的是扩展认证 (Authentication) 接口和 CAS Server 的界面。
我们通常都会使用jdbc连接数据库进行认证,这种情况,用户名和密码被保存在数据库的某个表中。需要进行如下配置。
用编辑器打开/webapps/cas-server-3.1.1/WEB-INF/deployerConfigContext.xml,找到如下xml,并注释掉该代码:
<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsername
PasswordAuthenticationHandler" />
在下面填写如下代码:
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="sql" value="select password from usertable where username=?" />
<property name="dataSource" ref="dataSource" />
</bean>
并添加一个bean:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">
<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
<property name="url"><value>jdbc:mysql://localhost:3306/test</value></property>
<property name="username"><value>test</value></property>
<property name="password"><value>test</value></property>
</bean>
假设使用数据库密码sd5加密,则增加配置如下:(红色部分是sd5加密配置)
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="sql" value="select password from usertable where username=?" />
<property name="passwordEncoder" ref="passwordEncoder"/>
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="passwordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder" autowire="byName">
<constructor-arg value="MD5"/>
</bean>
注意,再次部署,还需要增加几个包,做为依赖,如果使用maven,可以加入如下代码:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.12</version> </dependency> <dependency> <groupId>org.apache.openejb</groupId> <artifactId>commons-dbcp-all</artifactId> <version>1.3-r699049</version> </dependency>
如果您不使用maven管理的话,可以下载相应的包,并拷贝到WEB-INF/lib/中,重新启动tomcat即可。
创建表
mysql> create table user(id int,username char(100) NOT NULL,password char(100) NOT NULL,PRIMARY KEY (id));
mysql> insert into user values(2,'admin','admin123');
CAS提供了 RestFul API ,Restlet配置如下:
<dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-integration-restlet</artifactId> <version>3.4.11</version> <type>jar</type> </dependency>
然后再在 web.xml 中加入:
<servlet> <servlet-name>restlet</servlet-name> <servlet-class>com.noelios.restlet.ext.spring.RestletFrameworkServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>restlet</servlet-name> <url-pattern>/v1/*</url-pattern> </servlet-mapping>
地址:http://IP:8080/cas/v1/tickets
Spring security 3.1.x的首页讲了如何配置它到您的项目,在线官方文档请点击这里;跟CAS相关的章节请点击这里。3.0.X的SPRING官方也有讲解,再这里,讲的没有3.1.X的内容多。
CAS官方网站也给了个例子,用于于Spring security集成,不过讲的也不是很详细,可以点击这里查看。
国内的找了两篇写的可以的,点击 链接1,链接2 来查看。
可以参考这里。
参考这里。
以上都是Server端的配置,下一篇将会总结客户端的配置。
4.1证书的问题
在打证书的时候,输入了
您的名字与姓氏是什么?
经测试发现..如果caserver与单点服务在同一台电脑上,用key里注册的localhost访问是不会有问题的.但是如果不在同一台电脑上..内网访问也会出错!
所以这里不主张用localhost,可以用ip注册,内网访问用ip将不会有问题.(可是实际上CAS中也是不主张用IP来注册的)
另一个域名,将localhost改写成caserver单点所在服务器上的计算机名(右击我的电脑,属性,计算机名).测试通过!(这种方式虽然没有问题,但是必须把部署的机器名称改为此认证中的名称,比如master)
4.2 客户端只能使用域名来对中心发出申请,而不能使用IP。