软件及工具:
1. jdk: 1.8.0_131
2. tomcat 8.5.34
3. cas server : case-server-4.0.0-release.zip 点击下载
4. cas client: cas-client-3.3.3-release.zip 点击下载
5. window7 系统
jdk和 tomcat的安装此处省略...
steps:
1. 生成证书
1.1生成一个别名为 castest的证书
D:\Program Files\Java\jdk1.8.0_131\bin>keytool -genkey -alias castest -keyalg RSA -keystore F:\study\sso\cas\castest.crt
输入密钥库口令:
再次输入新口令:
您的名字与姓氏是什么?
[Unknown]: sso.castest.com => cas服务器跳转域名
您的组织单位名称是什么?
[Unknown]: lt
您的组织名称是什么?
[Unknown]: lt
您所在的城市或区域名称是什么?
[Unknown]: sz
您所在的省/市/自治区名称是什么?
[Unknown]: js
该单位的双字母国家/地区代码是什么?
[Unknown]: cn
CN=sso.castest.com, OU=lt, O=lt, L=sz, ST=js, C=cn是否正确?
[否]: y
输入 <castest> 的密钥口令
(如果和密钥库口令相同, 按回车):
此处 需要记住密码,后面导入证书 cas 服务器端会使用
1.2 导出证书
D:\Program Files\Java\jdk1.8.0_131\bin>keytool -export -file F:/study/sso/cas/cas.crt -alias castest -keystore F:/study/sso/cas/castest.crt
输入密钥库口令:
存储在文件 <F:/study/sso/cas/cas.crt> 中的证书
1.3 证书导入JRE
D:\Program Files\Java\jdk1.8.0_131\bin>keytool -import -keystore "D:\Program Files\Java\jdk1.8.0_131\jre\lib\security\cacerts" -file F:/study/sso/cas/cas.crt -a
lias castest
输入密钥库口令: 密码changeit (jvm默认密匙库密码)
所有者: CN=sso.castest.com, OU=lt, O=lt, L=sz, ST=js, C=cn
发布者: CN=sso.castest.com, OU=lt, O=lt, L=sz, ST=js, C=cn
序列号: f71f9d7
有效期开始日期: Tue May 09 17:27:11 CST 2017, 截止日期: Mon Aug 07 17:27:11 CST
2017
证书指纹:
MD5: 64:7D:08:00:25:F9:80:9D:DB:67:17:36:4C:5E:01:7E
SHA1: CF:0F:8F:95:E7:A3:B5:B2:D3:E5:30:A0:EC:58:C9:DD:BC:F4:A6:66
SHA256: 2A:4E:04:95:5D:68:A1:2A:32:9B:21:0E:B7:CE:14:04:DF:CA:18:E1:62:
83:D7:AF:58:42:B8:0C:69:0B:CC:AF
签名算法名称: SHA256withRSA
版本: 3
扩展:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 26 BA A1 F6 FD C7 FB D3 5D DC 0B 23 F0 2A 8F 99 &.......]..#.*..
0010: 91 4C CA 8C .L..
]
]
是否信任此证书? [否]: y
证书已添加到密钥库中
其中:D:\Program Files\Java\jdk1.8.0_131\jre\lib\security\cacerts为客户端JVM的密钥库位置
如果提示:
keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect
那么输入密码:changeit (jvm默认密匙库密码)
2. 配置服务端
1 、从http://developer.jasig.org/cas/上下载cas服务器端cas-server-4.0.0-release.zip,在modules目录下找到cas-server-webapp-4.0.0.war,将其复制到%TOMCAT_HOME%\webapps下,并将名称改为cas.war
2、修改%TOMCAT_HOME%\conf\server.xml文件
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystoreFile="F:/study/sso/cas/castest.crt"
keystorePass="123456"
clientAuth="false" sslProtocol="TLS" />
我这里用的 protocol 是 org.apache.coyote.http11.Http11NioProtocol
现在可以启动服务器了
3. 测试
https://localhost:8443
![](https://img-blog.csdn.net/20170510122613939?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3VodWFsb25nMTMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
如果此时可以正常访问,说明证书安装成功
打开 cas server https://localhost:8443/cas
![](https://img-blog.csdn.net/20170510122745955?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3VodWFsb25nMTMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
输入账号和密码 casuser/Mellon
![](https://img-blog.csdn.net/20170510123101377?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3VodWFsb25nMTMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
登录成功 这样 CAS服务器配置成功了
4. 配置客户端
1. 新建2个JAVA WEB 项目 CasClient01 和 CasClient02
2. 加压 cas-client-3.3.3 release.zip,在modules目录下找到cas-client-core-3.1.12.jar、commons-collections-3.2.jar、commons-logging-1.1.jar复制到项目WEB-INF/lib下
3. 添加映射域名,在C:\Windows\System32\drivers\etc\hosts文件中添加
127.0.0.1 sso.castest.com
4. 添加 web.xml文件 被添加如下配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>cas-demo</display-name>
<!-- ======================== 单点登录开始 ======================== -->
<!-- 用于单点退出,该过滤器用于实现单点登出功能,可选配置-->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- 该过滤器用于实现单点登出功能,可选配置 。 注意 登出的时候 配置客户端服务地址一定要用 IP 或者域名 否则 不能清除SESSION
(SSO Server发送logoutRequest 给SSO Client) -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/CasClient/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责用户的认证工作,必须启用它 -->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://sso.castest.com:8443/cas/login</param-value>
<!--这里的server是服务端的IP 正式发布可以改成 443 -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->
<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>
<param-value>https://sso.castest.com:8443/cas/</param-value><!-- 此处必须为登录url/cas/,带有任何其它路径都会报错,如“https://sso.castest.com:8443/cas/login”,这样也会报错。 -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value><!-- 服务器真实地址 -->
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
该过滤器负责实现HttpServletRequest请求的包裹,
比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。
-->
<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>
<!--
该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。
比如AssertionHolder.getAssertion().getPrincipal().getName()。
-->
<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>
<!-- ======================== 单点登录结束 ======================== -->
<!-- session超时定义,单位为分钟 -->
<session-config>
<session-timeout>2</session-timeout>
</session-config>
</web-app>
新建 index.jsp
在 CasClient01中内容为
<body>
CasClient01
<br/>
进入 <a href="http://localhost:8080/CasClient02/index.jsp">CasClient02</a>
</body>
在 CasClient02中内容为
<body>
CasClient02
<br/>
进入 <a href="http://localhost:8080/CasClient01/index.jsp">CasClient01</a>
</body>
重启tomcat
5. 测试
访问 http://localhost:8080/CasClient01/index.jsp 跳转到 cas server 登录页面
登录后跳转到实际访问页面 CasClient01下
这时 直接进入 CasClient02 系统 不需要在登录了
![](https://img-blog.csdn.net/20170510161607443?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3VodWFsb25nMTMxNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
至此, 简单的 CAS SERVER 和Cas CLIENT 演示搭建完成。
此时用户的验证是通过配置文件cas\WEB-INF\deployerConfigContext.xml中指定用户名和密码的方式进行验证的
<!-- 注释
<bean id="primaryAuthenticationHandler"
class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
<property name="users">
<map>
<entry key="casuser" value="Mellon"/>
</map>
</property>
</bean>-->
6. 数据库认证方式配置
打开 cas/WEB-INF/deployerConfigContext.xml
<!-- 注释 primaryAuthenticationHandler
<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
-->
<!--新增 dbAuthHandler-->
<entry key-ref="dbAuthHandler" value-ref="primaryPrincipalResolver" />
<!-- 注释
<bean id="primaryAuthenticationHandler"
class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
<property name="users">
<map>
<entry key="casuser" value="Mellon"/>
</map>
</property>
</bean>-->
<!-- 新增 Define the DB Connection -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://ip:3306/mydb?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8"
p:user="root"
p:password="password" />
<!-- Define the encode method-->
<bean id="passwordEncoder"
class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder"
c:encodingAlgorithm="MD5"
p:characterEncoding="UTF-8" />
<bean id="dbAuthHandler"
class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"
p:dataSource-ref="dataSource"
p:sql="select password from t_user where account=?"
p:passwordEncoder-ref="passwordEncoder"/>
最后,加入以下依赖包:c3p0-0.9.1.2.jar,MySQL-connector-Java5.1.21.jar,cas-server-support-jdbc-4.0.0.jar
重启tomcat服务器,发现已经可以使用数据库用户进行登录了。
数据库授权的相关日志
2017-05-10 16:51:31,306 INFO [org.jasig.cas.web.flow.InitialFlowSetupAction] - <Setting path for cookies to: /cas/>
2017-05-10 16:51:31,353 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: TGT-1-dQIhUKHfCe0tYlAiTb1bHaEPvzqrqpSjDGAWd0EgqhvIzZeTGe-cas01.example.org
ACTION: TICKET_GRANTING_TICKET_DESTROYED
APPLICATION: CAS
WHEN: Wed May 10 16:51:31 CST 2017
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================
>
2017-05-10 16:51:43,448 INFO [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <QueryDatabaseAuthenticationHandler successfully authenticated whl-test+password>
2017-05-10 16:51:43,449 INFO [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <Authenticated whl-test with credentials [whl-test+password].>
2017-05-10 16:51:43,449 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: supplied credentials: [whl-test+password]
ACTION: AUTHENTICATION_SUCCESS
APPLICATION: CAS
WHEN: Wed May 10 16:51:43 CST 2017
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================
>
2017-05-10 16:51:43,452 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: TGT-1-SRxa7O4HZIfUGQLoXr3N16PThde6DDnnKphlSJdcCYVMn9O9ih-cas01.example.org
ACTION: TICKET_GRANTING_TICKET_CREATED
APPLICATION: CAS
WHEN: Wed May 10 16:51:43 CST 2017
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================
>
2017-05-10 16:51:43,459 INFO [org.jasig.cas.CentralAuthenticationServiceImpl] - <Granted service ticket [ST-1-JygQAcQx9ufoQvBq4Vup-cas01.example.org] for service [http://localhost:8080/CasClient01/index.jsp] for user [whl-test]>
2017-05-10 16:51:43,459 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: whl-test
WHAT: ST-1-JygQAcQx9ufoQvBq4Vup-cas01.example.org for http://localhost:8080/CasClient01/index.jsp
ACTION: SERVICE_TICKET_CREATED
APPLICATION: CAS
WHEN: Wed May 10 16:51:43 CST 2017
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================
>
2017-05-10 16:51:43,543 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: ST-1-JygQAcQx9ufoQvBq4Vup-cas01.example.org
ACTION: SERVICE_TICKET_VALIDATED
APPLICATION: CAS
WHEN: Wed May 10 16:51:43 CST 2017
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================
>
2017-05-10 16:51:44,317 INFO [org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner] - <Beginning ticket cleanup.>
2017-05-10 16:51:44,317 INFO [org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner] - <0 tickets found to be removed.>
2017-05-10 16:51:44,317 INFO [org.jasig.cas.ticket.registry.support.DefaultTicketRegistryCleaner] - <Finished ticket cleanup.>
登出配置:
如果调用 /cas/logout 登出后 回到指定页面
1. 修改cas-servlet.xml文件的bean的id为logoutAction下的p:followServiceRedirects属性为“true”
<bean id="logoutAction" class="org.jasig.cas.web.flow.LogoutAction"
p:servicesManager-ref="servicesManager"
p:followServiceRedirects="${cas.logout.followServiceRedirects:false}"/>
或者 修改 cas-properties
# cas.logout.followServiceRedirects=true
2. 在自己系统要配置的系统“退出”链接后加上“?service=退出返回后的地址”,例如:CAS测试用的两个客户端的配置。例如:<ahref="http://sso.castest.com/cas/logout?service=
http://xxxx/casclient01/mainpage">退出</a>
3. 原理分析
从web.xml中可以看出 ,所有的请求都给 SafeDispatcherServlet进行处理分发
<servlet>
<servlet-name>cas</servlet-name>
<servlet-class>
org.jasig.cas.web.init.SafeDispatcherServlet
</servlet-class>
<init-param>
<param-name>publishContext</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/validate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/serviceValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/p3/serviceValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/proxy</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/proxyValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/p3/proxyValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/CentralAuthenticationService</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/status</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/statistics</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/authorizationFailure.html</url-pattern>
</servlet-mapping>
7. cas server 添加 restful api 能力
CAS-server提供了restful api供调用,要开启restful服务,首先要找到与之对应的jar包。
cas源代码里cas-server-integration-restlet这个工程就是支持restful的模块,编译出来后得到一个jar包,3.6之前的版本也可以直接下载到这个jar包。
把jar包cas-server-integration-restlet-3.5.2.jar,放到cas-server-webapp的lib目录下,除了这个jar包之外,还需要几个jar包,分别是:
com.noelios.restlet.ext.servlet,jar
com.noelios.restlet.ext.spring-1.1.0.jar
com.noelios.restlet.jar
org.restlet.ext.spring-1.1.10.jar
org.restlet-1.1.10.jar
都一并放到cas-server-webapp的lib目录下。
然后修改server的web.xml,加入一个restful的servlet
<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>
再找到WEB-INF\spring-configuration下的ticketExpirationPolicies.xml,把timetokill的这个时间改大一点,10秒有点短,手动测试的时候一下ticket就过期了
<util:constant id="SECONDS" static-field="java.util.concurrent.TimeUnit.SECONDS"/>
<bean id="serviceTicketExpirationPolicy" class="org.jasig.cas.ticket.support.MultiTimeUseOrTimeoutExpirationPolicy"
c:numberOfUses="1" c:timeToKill="${st.timeToKillInSeconds:10}" c:timeUnit-ref="SECONDS"/>
server端的配置基本就这么多,然后可以启动server的tomcat
最后就可以用restful的工具来进行测试了,我这里用的是curl
第一步是登录换取tgt
curl -i -k -X POST -d "username=lhc&password=123456&service=http://192.168.56.101/omw/do/main/index" https://192.168.56.101:8443/cas/v1/tickets/
会得到一个响应:
HTTP/1.1 201 Created
Date: Tue, 28 Jun 2016 08:03:23 GMT
Location: https://192.168.56.101:8443/cas/v1/tickets/TGT-3-MIipUxjOlXiXU1Uuj0vZncjZcfeIJFKhJwegBuHDL03kfCV5ME-cas01.example.org
Accept-Ranges: bytes
Server: Noelios-Restlet-Engine/1.1.6
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 448
把这个响应里的location字段后面的拷贝一下,这是第二步要访问的rest接口的url
curl -i -k -X POST -d "service=http%3A%2F%2F192.168.56.101%2Fomw%2Fdo%2Fmain%2Findex" https://192.168.56.101:8443/cas/v1/tickets/TGT-3-MIipUxjOlXiXU1Uuj0vZncjZcfeIJFKhJwegBuHDL03kfCV5ME-cas01.example.org
第二步的响应就是ticket
ST-2-AHrFkuIyZBarRPGHsbaZ-cas01.example.org
最后带上这个ticket访问上面service的地址,就是已经登录的状态
http://192.168.56.101/omw/do/main/index?ticket=ST-2-AHrFkuIyZBarRPGHsbaZ-cas01.example.org
curl里第二步的时候注意一下,这个url要进行编码。
其他:
异常1
错误CAS is Unavailable
修改超时时间试试: <bean id="terminateWebSessionListener" class="org.jasig.cas.web.flow.TerminateWebSessionListener"
p:timeToDieInSeconds="100"
/>