CAS单点登录技术实践

JDK 环境 1.7,操作系统windows,用户权限级别Adminstrator

web服务器:Tomcat 7

生成证书

CAS 通过证书来实现客户端与服务端的信息交互,所以第一步当然是生成证书了

通过JDK自带的工具keytool来生成证书

CAS单点登录技术实践

密码由自己创建,输入完输入的是域名,注意这个域名需要修改,在C:\Windows\System32\drivers\etc\hosts文件添加

127.0.0.1 sso.alingluo.com

将回环地址映射给sso.alingluo.com这个域名,输入其他信息

最后输入Y确认

二,导出证书

CAS单点登录技术实践

密码是刚刚创建的密码,证书导出完成,接下来就可以分发给客户端了

三,为客户端JVM导入证书

CAS单点登录技术实践

CAS单点登录技术实践

将证书添加到JVM的cacerts**库中,密码同上

四,应用证书到Tomcat

启用Tomcat的HTTPS加密协议,修改Tomcat目录下conf/server.xml文件并去掉注释,

keystoreFile为key存放路径,keystorePassword是创建证书时创建的密码

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="D:/keys/alingluokey" keystorePass="password"/>

五,配置CAS Server

从官网下载的cas server中会含有一个cas server对应的war包,对应路径为cas-server-3.5.2\modules\cas-server-webapp-3.5.2.war,我们可以把该war包重命名为cas.war,然后丢到tomcat的webapps目录下。

此外,由于CAS是基于Maven开发的,所以官方建议使用Maven的War覆盖机制。Maven的War覆盖机制是指当一个package类型为war的Maven项目A中引入了一个package类型为war的项目B作为依赖时,最终项目A打包的war包中不仅会包含项目A的内容,还会包含项目B的内容,且相同位置的文件项目A中的会覆盖项目B中的,即当项目A和项目B在WEB-INF下都拥有一个web.xml文件时,最终生成的war包中将使用项目A在WEB-INF下的web.xml文件;而当项目A在WEB-INF下没有web.xml文件,而项目B在WEB-INF下拥有web.xml文件时最终生成的war包中将使用项目B在WEB-INF下的web.xml文件。所以如果我们要修改Cas Server的配置文件,我们可以建立一个自己的基于Maven的Web项目,然后引入Cas Server作为依赖,并在自己的项目中建立对应的deployerConfigContext.xml文件。这有一篇教程:http://elim.iteye.com/blog/2128869

另附上Oracle数据源配置

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc.:oracle:thin:@localhost:1521:orcl" />
<property name="username" value="cas"/>
<property name="password" value="123456"/>
</bean>

配置完启动Tomcat服务器,访问https://localhost:8443/cas/login就可以看到登录页面了,输入数据库配置的用户名和密码进行认证

六,配置CAS Client

创建Maven Web项目

pom.xml依赖如下

<dependencies>
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<type>jar</type>
</dependency>
</dependencies>

编辑web.xml

<!--
按照顺序配置四个Filter
1,AuthenticationFilter
2,TicketValidationFilter
3,HttpServletRequestWrapperFilter
4,AssertionThreadLocalFilter
CAS Client默认会先从init-param取,没取到从context-param取
-->
<!--
AuthenticationFilter用来拦截所有的请求,用以判断用户是否需要通过CAS Server进行认证
必须指定Cas Server登录地址,casServerLoginUrl
认证成功后需要跳转地址的serverName或service,参数service具有更高的优先级
service指定一个确定的URL,serviceName指定的是主机名
-->
<context-param>
<param-name>serverName</param-name>
<param-value>http://sso.alingluo.com:8080</param-value>
</context-param>

<!-- 用于单点登出,该过滤器用于实现单点登出功能,可选配置 -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>

<!--
该过滤器用于实现单点登出功能,可选配置
-->
<filter>
<filter-name>casSingleSignout</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>casSingleSignout</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>casAuthentication</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://sso.alingluo.com:8443/cas/login</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>casAuthentication</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
在请求通过AuthenticationFilter认证之后,如果请求中携带了参数ticket
将会由TicketValidationFilter来对携带的ticket进行校验,多种验证ticket的Filter
都继承自AbstractTciketValidationFilter,使用的TicketValidation不一样
必须指定的参数,casServerUrlPrefix,用来指定CAS Server对于URL地址的前缀
serverName或service
-->
<filter>
<filter-name>casTicketValidationFilter</filter-name>
<filter-class>org.jasig.cas.client.validation.Cas10TicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://sso.alingluo.com:8443/cas</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>casTicketValidationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
HttpServletRequestWrapperFilter用于将每一个请求对应的HttpServletRequest
封装成内部定义的CasHttpServletRequestWrapper,利用Assertion对象重写getUserPrinicipal()方法
getRemoteUser()、isUserInRole()方法
-->
<filter>
<filter-name>casHttpServletRequestWrapper</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>casHttpServletRequestWrapper</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
AssertionThreadLocalFilter是方便获取Assertion对象,将当前Assertion对象存放到当前的线程变量中
-->

<filter>
<filter-name>casAssertionThreadLocalFilter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>casAssertionThreadLocalFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

到这里就配置完成了,访问客户端项目页面就会跳转到服务端登录页面(https://sso.alingluo.com:8443/cas/login)页面

错误集

CAS单点登录技术实践

TicketValidationFilter下的casServerUrlPrefix配置错误,应为cas Server登录路径的前缀,例如https://sso.alingluo.com:8443/cas

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

证书没有导入到客户端的JVM


CAS Client登录javax.net.ssl.SSLHandshakeException:Received fatal alert:handshake_faile

Jdk1.7无此问题,JDK1.6有此问题

Jvm启动参数中加入-Dhttps.protocols=SSLv3,TLSv1

在Tomcat的catalina.bat中开始行添加set JAVA_OPTS=-Dhttps.protocols=SSLv3,TLSv1

好像Tomcat官方文档不推荐修改catalina.bat文件,但是我懒嫌麻烦,还是修改了CAS单点登录技术实践

参考博文:http://www.iteye.com/blogs/subjects/cas168
http://blog.****.net/frinder/article/details/7969925

感谢他们的无私奉献!