CAS实现SSO单点登录
环境
cas-server-4.1.8,cas-client-3.4.0,Java-8,Maven-3,Tomcat-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.jar,mysql-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
|
< 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
|
< 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&useUnicode=true&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-client1,cas-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
|
<? 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 单点登录系统搭建结束。