资源准备
- cas-server-webapp-4.0.0.war
- c3p0-0.9.1.2.jar (版本不定,可用即可)
- mysql-connector-java-5.1.29.jar (版本不定,可用即可)
- cas-server-support-jdbc-4.0.0.jar
- cas-client-core-3.3.3.jar
- jcl-over-slf4j-1.7.7.jar
- jul-to-slf4j-1.7.7.jar
- log4j-1.2.16.jar、
- log4j-over-slf4j-1.7.7.jar
- logback-classic-1.1.2.jar
- logback-core-1.1.2.jar
- slf4j-api-1.7.7.jar
(加粗为必备资源)
基本配置
将下载好的cas-server-webapp-4.0.0.war
重命名为cas.war
并放到tomcat(默认版本为7,不建议使用更低版本的)的webapps
目录下。启动tomcat,解压。然后修改cas
的配置。
1. CAS的HTTP模式与HTTPS设置
- /cas/WEB-INF/deployerConfigContext.xml
增加p:requireSecure="false"
属性
<bean id="proxyAuthenticationHandler"
class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref="httpClient" p:requireSecure="false"/>
- /cas/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml
修改p:cookieSecure="true"
为p:cookieSecure="false"
.
<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
p:cookieSecure="false"
p:cookieMaxAge="-1"
p:cookieName="CASTGC"
p:cookiePath="/cas" />
- /cas/WEB-INF/spring-configuration/warnCookieGenerator.xml
修改p:cookieSecure="true"
为p:cookieSecure="false"
.
<bean id="warnCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
p:cookieSecure="false"
p:cookieMaxAge="-1"
p:cookieName="CASPRIVACY"
p:cookiePath="/cas" />
修改好上诉配置之后重启tomcat,访问localhost:8080/cas
可以进入CAS
的登录页面,登录用户名密码为casuser/Mellon
。可以从上面的deployerConfigContext.xml
中找到以下配置,即默认用户名密码配置。
<bean id="primaryAuthenticationHandler"
class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
<property name="users">
<map>
<entry key="casuser" value="Mellon"/>
</map>
</property>
</bean>
- 示例页面
(我这里配置了tomcat端口为80)
2. 配置数据库来验证用户
将列出的资源的c3p0-0.9.1.2.jar
、mysql-connector-java-5.1.29.jar
、cas-server-support-jdbc-4.0.0.jar
放入cas
的lib
目录下。修改配置,并重启tomcat。
* deployerConfigContext.xml
<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="dbAuthHandler" value-ref="primaryPrincipalResolver" />
<!-- <entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" /> -->
</map>
</constructor-arg>
.......
</bean>
......
<!--
<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://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull"
p:user="root"
p:password="root" />
<!-- 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 test.user_data where name=? and used=1"
p:passwordEncoder-ref="passwordEncoder"/>
(注意:其中的jdbcUrl
为你的数据库的url,user/password
同理,记得修改,密码为:MD5 32位 小写。另外sql
也可以根据自身习惯修改,数据库、表、数据记得创建。)
我这里添加了一条数据 casuser/Mellon(md5 32位 小写)
,重启之后继续访问localhost:8080/cas
,输入用户名密码,登陆成功!
keytool 生成https访问证书
学习链接 - java keytool 证书工具使用小结,详细命令参数可见该资料
1. 生成证书
注:命名及位置自己定义
keytool -genkey -alias michaelkey -keyalg RSA -keysize 1024 -keypass michaelpwd -validity 365 -keystore E:\sso\michael.keystore -storepass michaelpwd2
2. 查看证书
- -v 命令
keytool -list -v -keystore E:\sso\michael.keystore -storepass michaelpwd2
- -rfc 命令
keytool -list -rfc -keystore E:\sso\michael.keystore -storepass michaelpwd2
3. 导出证书
- 导出证书
keytool -export -alias michaelkey -keystore E:\sso\michael.keystore -file E:\sso\michael.crt -storepass michaelpwd2
- 查看导出的证书
keytool -printcert -file E:\sso\michael.crt
将证书导入到JAVA证书库
(注:这是使用一个新生成的证书:证书信息中名字与姓氏这一项必须填写你的访问的域名或者主机名,keypass 和 storepass 两个密码要一致,否则下面tomcat 配置https 访问失败;)
// 可以将生成的 crt 文件转换成 cer 文件
// 双击 --> 详细信息 --> 复制到文件 --> 选择导出文件格式 base64/二进制 (均为 .cer 文件)--> 命名 --> 完成
1. cmd 命令进入 dos --> cd C:\JDK\jre\lib\security
2. 输入命令行: keytool -import -alias ssodemo -keystore cacerts -file E:\sso\ssodemo.crt -trustcacerts
3. 输入密码: changeit (java 默认)
以后更新时,先删除原来的证书,然后导入新的证书
keytool -list -keystore cacerts -alias ssodemo
keytool -delete -alias ssodemo -keystore cacerts
keytool -import -alias ssodemo -file ssodemo.crt -keystore cacerts -trustcacerts
tomcat 配置 https
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
-->
修改为:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="E:/sso/ssodemo.keystore" keystorePass="michaelpwd"/>
启动tomcat,成功后访问tomcat,https://localhost:8443/
,会提示证书错误或不受信任,没有关系,选择继续访问。看到tomcat的默认页面说明配置成功。
多台 tomcat 模拟单点登录跳转
(注:至少两台 = = 不然怎么跳)
* 1. host 设置跳转域名
这里我们进行单机模拟实验,毕竟没有资源(你要是有资源,那你需要每台机器上面都有安装证书)。
127.0.0.1 cas.sso.com
127.0.0.1 app1.sso.com
...
- 2. 设置 tomcat
准备两台tomcat,重命名为:tomcat-cas、tomcat-app。tomcat-cas 按照上面的步骤:导入cas.war,修改配置,生成证书,导入证书到JAVA,配置https;访问
https://cas.sso.com:8443/
能够成功访问到cas登录页面,则OK。
下面来配置一下tomcat-app (能启动并访问,则OK。):
<!-- 修改 /conf/server.xml 修改端口号,使其能够正常启动 -->
<Server port="18005" shutdown="SHUTDOWN">
<Connector port="18080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="18443" />
<Connector port="18009" protocol="AJP/1.3" redirectPort="18443" />
- 使用tomcat自带的example项目进行模拟实验
1)添加cas client jar 包
找到 /WEB-INF/lib,添加 cas-client-core-3.3.3.jar,另外需要引入 log4j 的jar包,以支持 client 的日志,不然会报错,jcl-over-slf4j-1.7.7.jar、jul-to-slf4j-1.7.7.jar、log4j-1.2.16.jar、log4j-over-slf4j-1.7.7.jar、logback-classic-1.1.2.jar、logback-core-1.1.2.jar、slf4j-api-1.7.7.jar。版本自定,能用就行,咱们也只是做实验。
2)添加 filter
修改 web.xml 文件,添加 cas 访问需要的 filter,
<!-- ======================== 单点登录开始 ======================== -->
<!-- 该过滤器用于实现单点登出功能,可选配置。 -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<!-- 该过滤器负责用户的认证工作,必须启用它 -->
<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://cas.sso.com:8443/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://app1.sso.com:18080</param-value>
</init-param>
</filter>
<!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>org.jasig.cas.client.validation.Cas10TicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://cas.sso.com:8443/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://app1.sso.com:18080</param-value>
</init-param>
<init-param>
<param-name>redirectAfterValidation</param-name>
<param-value>true</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 Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
<!-- ======================== 单点登录结束 ======================== -->
<!-- 所有 filter 结束后添加 logout 的 listener -->
<!-- 用于单点退出 -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
启动 tomcat-cas 和 tomcat-app1 ,访问链接http://app1.sso.com:18080/examples/servlets/servlet/HelloWorldExample
,然后会跳转到 cas 的登录页面,输入用户名密码,跳转,成功,祝贺,普天同庆。
可以看到链接中附带了service=xxxx, 后面的地址就是http://app1.sso.com:18080/examples/servlets/servlet/HelloWorldExample
,设置一下字符集即可。
可以看到上图,附带了jsessionid。
至此,成功,但是还需要在实际开发中测试一下。
获取登陆成功用户名
修改example 项目的 HelloWorldExample.java
,并重新编译成.class
文件,
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import javax.servlet.*;
import javax.servlet.http.*;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.validation.Assertion;
/**
* CAS simple Servlet
*
* @author <a href="http://www.micmiu.com">Michael Sun</a>
*/
public class HelloWorldExample extends HttpServlet {
private static final long serialVersionUID = -6593274907821061823L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
ResourceBundle rb = ResourceBundle.getBundle("LocalStrings",
request.getLocale());
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
String title = rb.getString("helloworld.title");
out.println("<title>" + title + "</title>");
out.println("</head>");
out.println("<body bgcolor=\"white\">");
out.println("<a href=\"../helloworld.html\">");
out.println("<img src=\"../images/code.gif\" height=24 "
+ "width=24 align=right border=0 alt=\"view code\"></a>");
out.println("<a href=\"../index.html\">");
out.println("<img src=\"../images/return.gif\" height=24 "
+ "width=24 align=right border=0 alt=\"return\"></a>");
out.println("<h1>" + title + "</h1>");
Assertion assertion = (Assertion) request.getSession().getAttribute(
AbstractCasFilter.CONST_CAS_ASSERTION);
if (null != assertion) {
// 有效的开始时间
out.println(" Log | ValidFromDate =:"
+ assertion.getValidFromDate() + "<br>");
// 有效的结束时间
out.println(" Log | ValidUntilDate =:"
+ assertion.getValidUntilDate() + "<br>");
Map<String, Object> attMap = assertion.getAttributes();
out.println(" Log | getAttributes Map size = " + attMap.size()
+ "<br>");
for (Entry<String, Object> entry : attMap.entrySet()) {
out.println(" | " + entry.getKey() + "=:"
+ entry.getValue() + "<br>");
}
AttributePrincipal principal = assertion.getPrincipal();
// AttributePrincipal principal = (AttributePrincipal) request
// .getUserPrincipal();
String username = null;
out.print(" Log | UserName:");
if (null != principal) {
username = principal.getName();
out.println("<span style='color:red;'>" + username
+ "</span><br>");
}
}
out.println("</body>");
out.println("</html>");
}
}
启动tomcat,访问,如图:
可以分析出 CAS 登录成功后的一些结构:
Session
|| - Attribute
|| - Assertion
|| - ValidFromDate
- ValidUntilDate
- AttributePrincipal
|| - Name
可以自行查阅资料,了解更多。