Yale CAS最佳实践

Yale CAS最佳实践 第一部分:配置篇
1.环境准备
Jdk1.4.2

Tomcat5.0.28
cas-server-2.0.12(没有采用更高版本,是因为它最简单明了)
cas-client-java-2.1.1
2.在jdk上配置SSL
到http://java.sun.com/products/jsse/去下载jsse,我用的是1.0.3;下载下来后是一个zip包,把里边lib目录下的jar包复制到你的jdk目录下的jre/lib/ext目录中,是三个文件:jsse.jar;jnet.jar;jcert.jar

3.SSL验证证书
3.1.生成
keytool -genkey -alias tomcat -keyalg RSA
? 如果C:/Documents and Settings/Administrator/.keystore已经存在,请先删除。
? 输入tomcat本身的缺省口令changeit
? 用户前名和用户后名都用localhost
keytool -export -alias tomcat -file server.crt
只能输入tomcat的缺省口令changeit
keytool -import -trustcacerts -alias tomcat -file server.crt -keystore %java_home%/jre/lib/security/cacerts
3.2.显示
keytool -list -v -keystore %java_home%/jre/lib/security/cacerts > t.txt
3.3.删除
keytool -delete -alias tomcat -keystore  %java_home%/jre/lib/security/cacerts -keypass changeit
只能输入tomcat的缺省口令changeit
3.4.keytool参考
%JAVA_HOME%/bin/keytool -delete -alias tomcat -keypass changeit
%JAVA_HOME%/bin/keytool -genkey -alias tomcat -keypass changeit -keyalg RSA
%JAVA_HOME%/bin/keytool -export -alias tomcat -keypass changeit  -file %FILE_NAME%
%JAVA_HOME%/bin/keytool -import -file server.crt -keypass changeit
-keystore %JAVA_HOME%/jre/lib/security/cacerts
%JAVA_HOME%/bin/keytool -import -file server.crt -keypass changeit
%JAVA_HOME%/bin/keytool -genkey -alias tomcat -keypass changeit -keyalg RSA -validity 365

4.Tomcat配置
4.1.拷贝
拷贝C:/Documents and Settings/Administrator/.keystore到%tomcat_home%/conf/
4.2.配置
编辑%tomcat_home%/conf/server.xml,去掉ssl的注释,并更改为如下配置
    <Connector port="8443" keystorePass="changeit" keystoreFile="conf/.keystore"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" debug="0" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
4.3.注意
请保持C:/Documents and Settings/Administrator/.keystore与%tomcat_home%/conf/.keystore一致

5.Tomcat jmx bug
在sun网站上http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/download.jsp
下载jmx-1_2_1-ri.zip,解压后,把jmxri.jar重命名为jmx.jar,覆盖tomcat/bin目录下的jmx.jar
这个适用于cas-server-3.*


Yale CAS最佳实践 第二部分:原理篇

6.概念术语
CAS(Central Authentication Service)
TGT(Ticket Granting Ticket)
ST(Service Ticket)
PGT(Proxy Granting Ticket)
7.原理剖析
Yale CAS使用了Ticket Granting Cookie (简称TGC)去作为获取Service Ticket(简称ST)的凭据,这个TGC 是保存在客户端的cookie,即当第2次被其他CAS Client重定向的时候,CAS Server实际上已经从用户的Cookie中抓取到TGC,然后知道TGC对应的用户,因此避免了再次登录,如果CAS Server抓取不到TGC,则用户需要登陆。

众所周知,cookie是不能跨域的。但是CAS能够做abc.com和xyz.com的sso,因为CAS Server缓存了所有的ticket,所以Client无需共享cookies。

Yale CAS最佳实践 第三部分:源代码研读

8.源代码研读
8.1.web.xml参数定义:
edu.yale.its.tp.cas.client.filter.loginUrl: CAS server的login URL. (Required)
edu.yale.its.tp.cas.client.filter.validateUrl: CAS server的URL验证器. (Required)
edu.yale.its.tp.cas.client.filter.serviceUrl: URL of this service. (Required if serverName is not specified)
edu.yale.its.tp.cas.client.filter.serverName: 主机名:端口号
edu.yale.its.tp.cas.client.filter.authorizedProxy: 身份验证代理,用空格隔开.必须有一个. (缺省,只接受ST,不接受PT)
edu.yale.its.tp.cas.client.filter.proxyCallbackUrl: 本地代理回调监听器,用来接受PGT/PGTIOU. (可选)
edu.yale.its.tp.cas.client.filter.renew: 是否重新登录参数(缺省为false)
edu.yale.its.tp.cas.client.filter.gateway: 是否使用网关......虽然英文不难明白,但的确不懂到底有什么用,因而不敢断章取义,望哪位高手能补充一下,在此谢过
edu.yale.its.tp.cas.client.filter.wrapRequest: 封装了HttpServletRequest,重载了getRemoteUser()方法. 如果设置为"true", request.getRemoteUser()将返回登录用户名.(可选的,缺省为false.)
8.2.总体结构图

8.3.client源代码研读

8.4.server源代码研读

Yale CAS最佳实践 第四部分:试试身手

1.测试类
我写了一个RequestInfoServlet,可以显示HttpRequest的绝大部分有用信息,经过sso后,可以查看 HttpRequest里面还有什么东西。呵呵,我喜欢这样干。

Java代码 复制代码
  1. import java.io.IOException;   
  2. import java.io.PrintWriter;   
  3. import java.util.Enumeration;   
  4.   
  5. import javax.servlet.ServletException;   
  6. import javax.servlet.http.Cookie;   
  7. import javax.servlet.http.HttpServlet;   
  8. import javax.servlet.http.HttpServletRequest;   
  9. import javax.servlet.http.HttpServletResponse;   
  10. import javax.servlet.http.HttpSession;   
  11.   
  12. /**  
  13.  * @author Liujj Date 2006-12-19 <br>  
  14.  *         Description: <br>  
  15.  *         RequestHeadersServlet  
  16.  */  
  17. public class RequestInfoServlet extends HttpServlet {   
  18.     public void doGet(HttpServletRequest request, HttpServletResponse response)   
  19.             throws IOException, ServletException {   
  20.         response.setContentType("text/html");   
  21.         PrintWriter out = response.getWriter();   
  22.         //header   
  23.         Enumeration headerNames = request.getHeaderNames();   
  24.         out.println("<B>*********[1].begin print headerNames************</B><p>");   
  25.         while (headerNames.hasMoreElements()) {   
  26.             String name = (String) headerNames.nextElement();   
  27.             String value = request.getHeader(name);   
  28.             out.println(name + " = " + value + "<p>");   
  29.         }   
  30.         out.println("<B>*********[1].end print headerNames************</B><p><p>");   
  31.            
  32.         //attributeNames   
  33.         out.println("<B>*********[2].begin print attributeNames************</B><p>");   
  34.         Enumeration attributeNames = request.getAttributeNames();   
  35.         while (attributeNames.hasMoreElements()) {   
  36.             String name = (String) attributeNames.nextElement();   
  37.             String value = (String)request.getAttribute(name);   
  38.             out.println(name + " = " + value + "<p>");   
  39.         }   
  40.         out.println("<B>*********[2].end print attributeNames************</B><p><p>");   
  41.            
  42.         //parameterNames   
  43.         out.println("<B>*********[3].begin print parameterNames************</B><p>");   
  44.         Enumeration parameterNames = request.getParameterNames();   
  45.         while (parameterNames.hasMoreElements()) {   
  46.             String name = (String) parameterNames.nextElement();   
  47.             String value = request.getParameter(name);   
  48.             out.println(name + " = " + value + "<p>");   
  49.         }   
  50.         out.println("<B>*********[3].end print parameterNames************</B><p><p>");   
  51.            
  52.         //session   
  53.         out.println("<B>*********[4].begin print session AttributeNames************</B><p>");   
  54.         HttpSession session = request.getSession();   
  55.         Enumeration sAttributeNames = session.getAttributeNames();   
  56.         while (sAttributeNames.hasMoreElements()) {   
  57.             String name = (String) sAttributeNames.nextElement();   
  58.             Object value = session.getAttribute(name);   
  59.             out.println(name + " = " + value + "<p>");   
  60.         }   
  61.         out.println("<B>*********[4].end print session attributeNames************</B><p><p>");   
  62.            
  63.         //cookie   
  64.         out.println("<B>*********[4].begin print Cookie************</B><p><p>");   
  65.         Cookie[] cookie = request.getCookies();   
  66.         for(int i=0; i< cookie.length; i++) {   
  67.             String name = cookie[i].getName();   
  68.             String value = cookie[i].getValue();   
  69.             out.println(name + " = " + value + "<p>");   
  70.         }      
  71.         out.println("<B>*********[4].end print Cookie************</B><p><p>");   
  72.            
  73.     }   
  74.   
  75. }  
  76. 补充:关于cookie在哪里产生?
    login.sendTgc()
    Java代码 复制代码
    1. private TicketGrantingTicket sendTgc(String username,   
    2.         HttpServletRequest request, HttpServletResponse response)   
    3.         throws ServletException {   
    4.     try {   
    5.         TicketGrantingTicket t = new TicketGrantingTicket(username);   
    6.         String token = tgcCache.addTicket(t);   
    7.         Cookie tgc = new Cookie(TGC_ID, token);   
    8.         tgc.setSecure(true);   
    9.         tgc.setMaxAge(-1);   
    10.         tgc.setPath(request.getContextPath());   
    11.         response.addCookie(tgc);   
    12.         return t;   
    13.     } catch (TicketException ex) {   
    14.         throw new ServletException(ex.toString());   
    15.     }   
    16. }  
    	private TicketGrantingTicket sendTgc(String username,
    			HttpServletRequest request, HttpServletResponse response)
    			throws ServletException {
    		try {
    			TicketGrantingTicket t = new TicketGrantingTicket(username);
    			String token = tgcCache.addTicket(t);
    			Cookie tgc = new Cookie(TGC_ID, token);
    			tgc.setSecure(true);
    			tgc.setMaxAge(-1);
    			tgc.setPath(request.getContextPath());
    			response.addCookie(tgc);
    			return t;
    		} catch (TicketException ex) {
    			throw new ServletException(ex.toString());
    		}
    	}
    

web.xml范例: 
Java代码 复制代码
  1. <filter>   
  2.     <filter-name>CASFilter</filter-name>   
  3.     <filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class>   
  4.     <init-param>   
  5.         <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name>   
  6.         <param-value>https://Solaris4Oracle:8443/cas/login</param-value>   
  7.     </init-param><!--这里的server是服务端的IP-->   
  8.     <init-param>   
  9.         <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>   
  10.         <param-value>https://Solaris4Oracle:8443/cas/proxyValidate</param-value>   
  11.     </init-param><!--这里的serName是服务端的主机名,而且必须是-->   
  12.     <init-param>   
  13.       <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>   
  14.       <param-value>192.168.6.167:8080</param-value><!--client:port就是需要CAS需要拦截的地址和端口,一般就是这个TOMCAT所启动的IP和port-->   
  15.     </init-param>   
  16. </filter>  

 

不配置client的host文件指定cas服务器域名方法:

修改edu.yale.its.tp.cas.util.SecureURL类:

/**
* 从输入流中提取字�符
*
* @Date 2007-3-4 <br>
* @param in
*            输入�流
* @param encode
*            字符编码
* @return 字符
*/
public static final String getHtmlString(InputStream in, String encode)
throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(in));
String line;
StringBuffer buf = new StringBuffer();
while ((line = r.readLine()) != null)
buf.append(line + "/n");
return buf.toString();
}
// /**
// * Retrieve the contents from the given URL as a String, assuming the
//     * URL's server matches what we expect it to match.
//     */
//    public static String retrieve(String url) throws IOException {
//    if (log.isTraceEnabled()){
//    log.trace("entering retrieve(" + url + ")");
//    }
//        BufferedReader r = null;
//        try {
//            URL u = new URL(url);
//            if (!u.getProtocol().equals("https")){
//            // IOException may not be the best exception we could throw here
//            // since the problem is with the URL argument we were passed, not
//            // IO. -awp9
//            log.error("retrieve(" + url + ") on an illegal URL since protocol was not https.");
// throw new IOException("only 'https' URLs are valid for this method");
//            }
//               
//            URLConnection uc = u.openConnection();
//            uc.setRequestProperty("Connection", "close");
//            r = new BufferedReader(new InputStreamReader(uc.getInputStream()));
//            String line;
//            StringBuffer buf = new StringBuffer();
//            while ((line = r.readLine()) != null)
//                buf.append(line + "/n");
//            return buf.toString();
//        } finally {
//            try {
//                if (r != null)
//                    r.close();
//            } catch (IOException ex) {
//                // ignore
//            }
//        }
//    }

转载:http://www.javaeye.com/topic/40129

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值