一、SSO (Single Sign-on)原理
SSO 分为Web-SSO和桌面SSO。桌面 SSO 体现在操作系统级别上。Web-SSO体现在客户端,主要特点是: SSO 应用之间使用 Web 协议( 如 HTTPS) ,并且只有一个登录入口。我们所讲的SSO,指 Web SSO 。
SSO 的体系中,有下面三种角色:
- User(多个)
- Web应用(多个)
- SSO认证中心(一个)
SSO 实现模式千奇百怪,但万变不离其宗,包含以下三个原则:
- 所有的登录都在 SSO 认证中心进行。
- SSO 认证中心通过一些方法来告诉 Web 应用当前访问用户究竟是不是通过认证的用户。
- SSO 认证中心和所有的 Web 应用建立一种信任关系。
二. CAS 的基本原理
CAS(Central Authentication Service) 是 Yale 大学发起的构建 Web SSO 的 Java开源项目。
1.CAS 的结构体系
1)CAS Server
CAS Server 负责完成对用户信息的认证,需要单独部署,CAS Server 会处理用户名 / 密码等凭证 (Credentials) 。
2)CAS Client
CAS Client部署在客户端,当有对本地 Web 应用受保护资源的访问请求,并且需要对请求方进行身份认证,重定向到 CAS Server 进行认证。
2. CAS 协议.
基础协议
上图是一个基础的 CAS 协议, CAS Client 以 过滤器的方式保护 Web 应用的受保护资源,过滤从客户端过来的每一个 Web 请求,同时,CAS Client 会分析 HTTP 请求中是否包请求 Service Ticket( 上图中的 Ticket) ,如果没有,则说明该用户是没有经过认证的, CAS Client会重定向用户请求到 CAS Server ( Step 2 )。 Step 3 是用户认证过程,如果用户提供了正确的认证信息 , CAS Server 会产生一个随机的 Service Ticket ,会向 User 发送一个 Ticket granting cookie (TGC) 给 User 的浏览器,并且重定向用户到 CAS Client (附带刚才产生的Service Ticket),Step 5 和 Step6 是 CAS Client 和 CAS Server 之间完成了一个对用户的身份核实,用 Ticket 查到Username ,认证通过。
3. CAS 如何实现 SSO
当用户访问Helloservice2再次被重定向到 CAS Server 的时候, CAS Server 会主动获到这个 TGC cookie ,然后做下面的事情:
1) 如果 User 的持有 TGC 且其还没失效,那么就走基础协议图的 Step4 ,达到了 SSO 的效果。
2) 如果 TGC 失效,那么用户还是要重新认证 ( 走基础协议图的 Step3) 。
三.安全证书配置并实践
下面我们以tomcat 8.0 为例进行说明(这里,我将Server和Client同时放在了同一个Tomcat服务器下)。
软件环境:tomcat 8.0 ant-1.6.5, jdk1.7.0_06
下载cas-server-4.0.0.zip和cas-client3.3.3和mysql 5.0.16和tomcat 8
CAS之下载地址(包含server和client)
http://downloads.jasig.org/将cas-server-4.0.0.zip解压,并将\cas-server-4.0.0\modules中的cas-server-webapp-4.0.0.war该名为cas.war并将cas.war拷贝到tomcat\webapps下。
有关keytool工具的详细运用见:http://www.micmiu.com/lang/java/keytool-start-guide/
1.我们在tomcat下建立一个keystore文件夹,在此文件夹中生成证书文件,打开命令窗口,进入此目录下,如图:
2.生成服务器端证书,,执行完此命令keystore文件夹下多了一个(.keystore)文件,设置的默认密码(changeit)。
命令:keytool -genkey -alias sxsso -keyalg RSA -keystore ./.keystore
3.导出服务器端证书,执行完此命令keystore文件夹下多了一个sxsso.cer文件
命令:keytool -export -alias server -storepass changeit -file server.cer -keystore server.keystore
4.导入服务器端证书,因为是在本地测试所以导入证书到JDK.
命令:keytool -import -keystore "D:\tool\Java\jdk1.8.0_45\jre\lib\security\cacerts" -file ./sxsso.crt -alias sxsso -storepass changeit
此时已经把证书导入到java中的JDK中了。此时登录 http://127.0.0.1:8080/cas/login 时会出现以下画面。
现在就需要我们到tomcat/conf/sever.xml修改找到:
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
-->
在下面添加
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="D:/tool/apache-tomcat-8.0.21/keystore/.keystore" keystorePass="changeit"/>
并把
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
修改为
<Connector port="8080" protocol="org.apache.coyote.http11.Http11Protocol"
connectionTimeout="20000"
redirectPort="8443" />
输入URL https://127.0.0.1:8443/cas/login 就会出现以下页面
使用CAS SSO中默认的用户名与密码登录(casuser/Mellon),路径为: D:\tool\apache-tomcat-8.0.21\webapps\cas\WEB-INF\deployerConfigContext.xml 有以下数据:
注:博主用在所后添加用CAS SOO使用数据库验证验证来用户名、密码验证。
ok.你成功了吗?
四. 客户端中项目配置
在要使用CAS的客户端应用里设置(应用时,所有客户端均进行类似配置),我们使用ServletFilter(CAS client里提供的)来实现SSO的检查。
修改&{progrem}/WEB-INF/web.xml
<!-- 用于单点登录拦截验证 -->
</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>
<param-value>https://sso.rying.com:8443/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<!-- 请求参数ticket验证(ticket即子系统与CAS系统进行交互的凭证) -->
<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.rying.com:8443/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<!--
该过滤器负责实现HttpServletRequest请求的包裹,
比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。
-->
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<!--
该过滤器使得开发者可以通过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 Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
五.CAS 安全性
TGC/PGT 安全性
TGC 也有自己的存活周期。下面是 CAS 的 applicationContext.xml 中,通过 TimeoutExpirationPolicy来设置 CAS TGC 存活周期的参数,参数默认是 120 分钟,在合适的范围内设置最小值,太短,会影响 SSO 体验,太长,会增加安全性风险。
<bean id="grantingTicketExpirationPolicy" class="org.jasig.cas.ticket.support.TimeoutExpirationPolicy">
<!-- This argument is the time a ticket can exist before its considered expired. -->
<constructor-arg index="0" value="7200000" />//单位为:毫秒
</bean>
Service Ticket/Proxy Ticket 安全性
设用户拿到 Service Ticket 之后,他请求 helloservice 的过程又被中断了, Service Ticket 就被空置了,事实上,此时, Service Ticket 仍然有效。 CAS 规定 Service Ticket 只能存活一定的时间,然后 CAS Server 会让它失效。通过在 applicationContext.xml 中配置下面的参数, 可以让 Service Ticket 在访问多少次或者多少秒内失效。
<!-- Expiration policies -->
<bean id="serviceTicketExpirationPolicy" class="org.jasig.cas.ticket.support.MultiTimeUseOrTimeoutExpirationPolicy">
<!-- This argument is the number of times that a ticket can be used before its considered expired. -->
<constructor-arg index="0" value="1" />
<!-- This argument is the time a ticket can exist before its considered expired. -->
<constructor-arg index="1" value="300000" />//单位:毫秒
</bean>
该参数在业务应用的条件范围内,越小越安全。
软件环境:tomcat 8.0 ant-1.6.5, jdk1.7.0_06
下载cas-server-4.0.0.zip和cas-client3.3.3和cas-server-jdbc-4.0.0-rc2.jar和mysql 5.0.16和tomcat 8
CAS之下载地址
http://downloads.jasig.org/