环境

cas-server-4.1.8cas-client-3.4.0Java-8Maven-3Tomcat-7.0.72

CAS Server 安装

点此进入 CAS 下载列表选择下载 cas-4.1.8.zip

解压缩 cas-4.1.8.zip 并进入 cas-server-webapp 目录在当前目录打开 cmd 并执行安装命令

1
mvn -e -ff clean install -Dmaven.test.skip=true

经亲身测试(自己拉的电信12M网络)该安装过程非常漫长主要因为镜像原因导致依赖包下载非常慢此过程需静心等待或直接下载我已经打好包的 cas.war 文件(注:该文件的依赖包版本有稍做修改此不影响正常使用)

安装完成后在 cas-server-webapp/target 目录下可以看到 cas.war 文件该文件便是 cas server 应用服务的 war 包

cas server 安全认证是基于 https 的这里使用 JDK 自带的 keytool 工具生成数字证书生产环境系统的应用需要到证书提供商处购买证书证书的生成及 Tomcat 的配置可参考文章:keytool 生成数字证书 - tomcat https 配置

首先确保 tomcat 的 https 可以正常访问将 cas.war 文件拷贝到 apache-tomcat-7.0.72/webapps 下进行发布启动 tomcat访问 https://www.fanlychie.com:8443/cas

上图是用火狐浏览器打开的链接选择高级 -> 添加例外 -> 确认安全例外

用户名和密码在 apache-tomcat-7.0.72/webapps/cas/WEB-INF/deployerConfigContext.xml 配置文件中找到并打开该文件大概在 105 行

1
2
3
4
5
6
7
8
<bean id="primaryAuthenticationHandler"
class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
<property name="users">
<map>
<entry key="casuser" value="Mellon" />
</map>
</property>
</bean>

可以看到默认的用户名是 casuser密码是 Mellon

看到上图的页面表明 cas server 已经部署成功

CAS Server 配置基于数据库用户认证

回到 cas-4.1.8.zip 解压缩的目录并进入 cas-server-support-jdbc 目录在当前目录打开 cmd 并执行安装命令

1
mvn -e -ff clean install -Dmaven.test.skip=true

安装完成后在 target 目录得到 cas-server-support-jdbc-4.1.8.jar 文件

将该文件拷贝到 apache-tomcat-7.0.72/webapps/cas/WEB-INF/lib 目录下并向此目录添加 c3p0-0.9.1.2.jarmysql-connector-java-5.1.17.jar 两个文件嫌麻烦的话点此下载这三个 jar 包的压缩包文件

再次打开 apache-tomcat-7.0.72/webapps/cas/WEB-INF/deployerConfigContext.xml 文件大概在第 54 行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
<constructor-arg>
<map>
<!--
| IMPORTANT
| Every handler requires a unique name.
| If more than one instance of the same handler class is configured, you must explicitly
| set its name to something other than its default name (typically the simple class name).
-->
<entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
<!-- 注销此项
<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
-->
<!-- 添加此项 -->
<entry key-ref="myAuthenticationHandler" value-ref="primaryPrincipalResolver" />
</map>
</constructor-arg>
<!-- Uncomment the metadata populator to capture the password.
<property name="authenticationMetaDataPopulators">
<util:list>
<bean class="org.jasig.cas.authentication.CacheCredentialsMetaDataPopulator"/>
</util:list>
</property>
-->
<!--
| Defines the security policy around authentication. Some alternative policies that ship with CAS:
|
| * NotPreventedAuthenticationPolicy - all credential must either pass or fail authentication
| * AllAuthenticationPolicy - all presented credential must be authenticated successfully
| * RequiredHandlerAuthenticationPolicy - specifies a handler that must authenticate its credential to pass
-->
<property name="authenticationPolicy">
<bean class="org.jasig.cas.authentication.AnyAuthenticationPolicy" />
</property>
</bean>

按以上配置注销掉第二个 entry 并添加一个 entry接着在后面添加两个 bean 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/cas_test_db?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=utf-8" />
<property name="user" value="root" />
<property name="password" value="root" />
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="initialPoolSize" value="10" />
<property name="maxIdleTime" value="1800" />
<property name="maxPoolSize" value="60" />
<property name="acquireIncrement" value="5" />
<property name="acquireRetryAttempts" value="60" />
<property name="acquireRetryDelay" value="2000" />
<property name="breakAfterAcquireFailure" value="false" />
<property name="autoCommitOnClose" value="false" />
<property name="checkoutTimeout" value="30000" />
<property name="idleConnectionTestPeriod" value="900" />
</bean>
<bean id="myAuthenticationHandler" class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"
p:dataSource-ref="dataSource"
p:sql="SELECT passwd FROM user WHERE name = ?" />

其中 cas_test_db 数据库中的 user 建表语句为

1
2
3
4
5
6
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`passwd` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
)

重启 tomcat访问 https://www.fanlychie.com:8443/cas用数据库中的 name/passwd 作为用户名和密码登录系统若登录成功表明配置已成功

CAS Client 客户端使用和配置

使用 maven 创建两个 web 项目 cas-client1cas-client2点此下载 demo 文件

cas-client1 项目 pom.xml 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<dependencies>
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<port>8881</port>
<httpsPort>8081</httpsPort>
<uriEncoding>UTF-8</uriEncoding>
<protocol>org.apache.coyote.http11.Http11NioProtocol</protocol>
<clientAuth>false</clientAuth>
<keystoreFile>C:\Users\fanlychie\.keystore\selfissue.jks</keystoreFile>
<keystorePass>123654</keystorePass>
<keystoreType>JKS</keystoreType>
<url>http://localhost:8081/manager/html</url>
</configuration>
</plugin>
</plugins>
</build>

首先必须确保项目 https 协议可以正常访问否则 cas server 无法认证

选中项目 -> Run As -> Maven build… -> tomcat7:run

访问 https://www.fanlychie.com:8081若能访问到表明 tomcat 已准备好

cas-client1 项目 web.xml 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<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>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<!-- 此处配置的是 cas server 地址 -->
<param-value>https://www.fanlychie.com:8443/cas</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
<!-- 此处配置的是 cas server 登录地址 -->
<param-value>https://www.fanlychie.com:8443/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<!-- 此处配置的是当前项目地址, 且必须使用 https 服务, 否则 cas server 无法认证 -->
<param-value>https://www.fanlychie.com:8081</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
<!-- 此处配置的是 cas server 地址 -->
<param-value>https://www.fanlychie.com:8443/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<!-- 此处配置的是当前项目地址, 且必须使用 https 服务, 否则 cas server 无法认证 -->
<param-value>https://www.fanlychie.com:8081</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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 Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

以上是 cas client 标准配置具体信息可参考 https://github.com/apereo/java-cas-client

cas-client2 配置基本与 cas-client1 配置相同详情可见 demo同时启动这两个项目

cas-client1 - https://www.fanlychie.com:8081

cas-client2 - https://www.fanlychie.com:8082

访问其中的一个项目 https://www.fanlychie.com:8081会自动跳到

https://www.fanlychie.com:8443/cas/login?service=https%3A%2F%2Fwww.fanlychie.com%3A8081%2F

由于还没有登录过 CAS 认证系统CAS 认证系统拦截到你的访问进入到认证系统登录界面当登录成功后CAS 服务会跳转向到你刚刚访问的地址

当你访问 https://www.fanlychie.com:8082此时是不需要登录了的

至此CAS 实现 SSO 单点登录系统搭建结束