1. 开发说明 
1.1. 开发目的 
  为了满足portal门户与各个子系统统一登录的需求,从而使用CAS进行SSO单点登录的配置开发。此开发文档是在开发过程中编写整合,提供项目组开发人员做为参考。
1.2. 预期读者 
(1)系统设计人员
(2)平台开发人员
(3)系统维护人员
1.3. 开发资源 
开发中所使用的资源版本如下说明,不同的版本所使用的配置方法及开发步骤不同,请注意相应的版本号。
环境要求
    
        
            | 
             JDK 1.4.2 
             | 
        
        
            | 
             Websphere6.0.2.15 
             | 
        
    
  开发使用Liferay portal 4.3.0门户平台框架,测试环境使用liferay绑定的tomacat5.X+JDK1.4,可以从http://www.liferay.com/官网上下载其绑定的相关版本进行整合开发。
  单点登陆服务端使用liferay整合后的liferay-portal-cas-web-4.3.0.war进行配置,其集成使用的CAS版本为cas-server-3.0.5.jar,客户端使用CAS Client2.11;相关资料文档可查看http://www.ja-sig.org/products/cas/相关文档。
2. CAS-SERVER 
2.1. 项目说明 
    CAS是Yale大学的ITS开发的一套JAVA实现的开源的SSO的服务。该服务是以一个java web app(eg:cas.war)来进行服务的,使用时需要将cas.war发布到一个servlet2.3兼容的服务器上,并且服务器需要支持SSL,在需要使用该服务的其他服务器(客户端),配置相应的以fitle实现SSO。
  在liferay portal项目中,使用自已集成的liferay-portal-cas-web-4.3.0.war,也可在cas的官方站点中下载相应原码cas-server-3.0.5.zip进行修改!
2.2. 目录结构 
下载cas-server-3.0.5.zip后进行解压,将原码core"src导入至eclipse中,目录结构如下:

在cas-server项目中需增加身份验证,使用portal项目用户表[lportal.user_]进行登录,为了程序开发的方便,我们将使用portal集成liferay-portal-cas-web-4.3.0.war的项目新建web项目进行server端的修改测试工作。
3. CAS WEB应用 
3.1. 项目说明 
  在lifreay项目中下载liferay-portal-cas-web-4.3.0.war,里面集成了SSO单点登录的开发方法。
将项目导入eclipse进行二次开发。
使用liferay portal进行CAS Server配置,其配置方法在liferay官方文档中有详细的说明:
http://content.liferay.com/4.3/doc/installation/liferay_4_installation_guide/multipage/ch05s04.html
1、下载Liferay-portal-cas-4.3.x.war;下载地址 www.liferay/web/guest/downloads
2、并将下载的war更名为cas.war,发布至tomcat下,进行相关设置。具体的发布方法需进行数字签名和tomcat环境配置工作。
3、系统发布测试。
3.2. 目录结构 
将war包解压导入至eclpise进行开发整合,我们使用web项目进行修改发布。
导入后的目录如下:

3.3. 页面改造 
Ø CAS汉化改造:
在src下使用eclipse的properties插件翻译messages.properties,如:
screen.welcome.welcome=欢迎您进入PORTAL平台 
Ø CAS页面改造:
对基本的登录登出页面及布局进行改造,以适合信息平台的需要,具体的改造页面主要包括:
"cas"WEB-INF"view"jsp"default"ui"casLoginView.jsp —登录页面
"cas"WEB-INF"view"jsp"default"ui"casLogoutView.jsp —登出页面
"cas"WEB-INF"view"jsp"default"ui"casLogoutView.jsp —登出页面
"cas"WEB-INF"view"jsp"default"ui"casGenericSuccess.jsp —录成功页面
"cas"WEB-INF"view"jsp"default"ui"includes"top.jsp —包含的头文件
"cas"WEB-INF"view"jsp"default"ui"includes"bottom.jsp —包含的头脚文件
......
3.4. 授权改造 
CAS跟普通的Web系统融合认证和授权,需增加java授权文件,此文件继承AbstractUsernamePasswordAuthenticationHandler ,并进行验证。
1、在src下增加DBHandlers.java
DBHandlers
    
        
            | 
             package com.yitong.cas.auth.provider; 
            import java.sql.Connection; 
            import java.sql.ResultSet; 
            import java.sql.Statement; 
            import javax.naming.Context; 
            import javax.naming.InitialContext; 
            import javax.sql.DataSource; 
            import org.apache.log4j.Logger; 
            import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler; 
            import org.jasig.cas.authentication.principal.UsernamePasswordCredentials; 
            /**   
             * @author soju   
             * @version 1.0   
             *   
             */ 
            public final class DBHandlers extends 
              AbstractUsernamePasswordAuthenticationHandler { 
             private Logger log = Logger.getLogger(DBHandlers.class); 
             /**   
              * 相关的数据库配置DS对应的jndi   
              */ 
             private String _jndi = "lportal"; 
             public boolean authenticateUsernamePasswordInternal( 
               final UsernamePasswordCredentials credentials) { 
              String username = credentials.getUsername(); 
              String password = credentials.getPassword(); 
              log.info("username:" + username); 
              log.info("password:" + password); 
              try { 
                     password = Security.encryptMD5(password);    
               log.debug("md5password" + password); 
              } catch (Exception e) { 
               log.warn("MD5加密出错", e); 
               throw new Exception("MD5加密出错");    
               return false; 
              } 
              try { 
               if (checkuser(username, password) == 1) { 
                getLog().info("认证成功!"); 
                return true; 
               } 
              } catch (Exception e) { 
               log.warn("failed authentication", e); 
              } 
              return false; 
             } 
             private int checkuser(String user, String pwd) throws Exception { 
              int ok= 0; 
              Context initCtx = new InitialContext(); 
              DataSource ds = (DataSource) initCtx.lookup(_jndi); 
              Connection conn = ds.getConnection(); 
              String sql = "select * from user_ where screenname='"+ user + "' and password_='" + pwd + "' "; 
              log.info("sql= " + sql); 
              Statement st = conn.createStatement(); 
              ResultSet rs = st.executeQuery(sql); 
              log.info("登录成功!"); 
              if (rs.next()) { 
               Ok=1; 
              } else { 
               log.info("帐号不存在或密码错误!"); 
              } 
              conn.close(); 
              return rei; 
             } 
             protected void afterPropertiesSetInternal() throws Exception { 
              super.afterPropertiesSetInternal();  
             } 
            } 
             | 
        
    
2、修改WEB-INF"deployerConfigContext.xml下文件:
    
        
            | 
             <bean class="org.jasig.cas.authentication.handler.support. 
            SimpleTestUsernamePasswordAuthenticationHandler" /> 
            <bean class="com.yitong.cas.auth.provider.DBHandlers" /> 
             | 
        
    
将此项目在tomcat中进行测试,当然首先配置数字签名及tomcat测试环境
4. 数字签名 
4.1. 生成密钥 
设置你的JDK_HOME;将JDK的BIN加入系统变量中或是直接在jdk bin下使用如下命令
在CMD下输入如下命令:
keytool -genkey -alias cas -keyalg RSA -keysize 1024 -validity 3650 -keystore ${USER_ROOT }/keystore.jks
    
        
            | 
             输入keystore密码:  changeit 
            您的名字与姓氏是什么? 
              [Unknown]:  xxx.xxx.xxx..xxx 
            您的组织单位名称是什么? 
              [Unknown]: 
            您的组织名称是什么? 
              [Unknown]: 
            您所在的城市或区域名称是什么? 
              [Unknown]: 
            您所在的州或省份名称是什么? 
              [Unknown]: 
            该单位的两字母国家代码是什么 
              [Unknown]: 
            CN=192.168.13.100, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown 正确 
            吗? 
              [否]:  y 
            输入<cas>的主密码 
                    (如果和 keystore 密码相同,按回车): 
             | 
        
    
说明:
1、 cas 为密钥的别名;
2、 您的名字与姓氏是什么提示时请输入你所在server的域名或IP地址,即你发布的websphere 所在的域名或IP地址,如192.168.1.100
3、 ${USER_ROOT }/keystore.jks为您所生成的文件存放目录。
4、 可使用命令查看证书内容
    
        
            | 
             C:">keytool -list -keystore ${USER_ROOT }/keystore.jks 
            输入keystore密码:  changeit 
            Keystore 类型: jks 
            Keystore 提供者: SUN 
            您的 keystore 包含 2 输入 
            websphere, 2007-12-19, keyEntry, 
            认证指纹 (MD5): 42:F8:BD:B2:C1:5B:9B:17:33:F2:05:AF:41:31:8B:FC 
            casserver, 2007-12-19, keyEntry, 
            认证指纹 (MD5): 66:47:03:0C:FC:D2:3E:18:80:98:3F:5B:C5:84:5E:9E 
             | 
        
    
4.2. 导出证书 
keytool -export -alias cas -keystore ${USER_ROOT }/keystore.jks -file ${USER_ROOT }/cas.cer
    
        
            | 
             输入keystore密码:  changeit 
            保存在文件中的认证 <${USER_ROOT }/cas.cer> 
             | 
        
    
说明:
将密钥cas导成cas.cer证书文件;${USER_ROOT }为导出的目录
4.3. 导入证书 
keytool -import -alias casserver -keystore %JAVA_HOME%/jre/lib/security/cacerts  -file ${USER_ROOT }/cas.cer  -trustcacerts
    
        
            | 
             输入keystore密码:  changeit 
            Owner: CN=xxx.xxx.xxx.xxx, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown 
            发照者: CN=xxx.xxx.xxx.xxx, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unkn 
            own 
            序号: 47690c06 
            有效期间: Wed Dec 19 20:18:14 CST 2007 至: Sat Dec 16 20:18:14 CST 2017 
            认证指纹: 
                     MD5:  66:47:03:0C:FC:D2:3E:18:80:98:3F:5B:C5:84:5E:9E 
                     SHA1: F8:D5:B7:5D:20:F8:61:32:D0:1D:99:61:89:40:BF:73:6C:84:BA:58 
            信任这个认证? [否]:  y 
            认证已添加至keystore中 
             | 
        
    
说明:
1、 导入${USER_ROOT }/cas.cer证书文件;
2、 %JAVA_HOME%/jre/lib/security/cacerts为您服务器所使用的JVAV环境里,将证书导入至JVM中。
5. Tomcat配置 
1、修改配置:tomcat"conf" server.xml
    
        
            | 
                 <Connector port="8443" maxHttpHeaderSize="8192" 
                           maxThreads="150" minSpareThreads="25" maxSpareThreads="75" 
                           enableLookups="false" disableUploadTimeout="true" 
                           acceptCount="100" scheme="https" secure="true" 
                           clientAuth="false"  
                  keystoreFile="${USER_ROOT }/ keystore.jks"  
                  keystorePass="changeit" 
                  sslProtocol="TLS">    
             </Connector> 
             | 
        
    
2、根据生成的 keystore.jks,导入至web server所使用的JVM,设置完成后重新启动tomcat,进行页面测试。
3、测试路径:https://server IP:8443/cas

6. CAS-CLIENT 
6.1. 配置要求 
  CAS 的客户端可以有很多种,因为验证的结果是以XML的格式返回的,故可以根据
需要实现一个自己的客户端。
http://www.yale.edu/tp/cas/cas-client-2.0.11.zip
http://www.ja-sig.org/products/cas/client/index.html
开发所需配置包,注意版本问题,会因版本开发的client不同
    
        
            | 
             包名 
             | 
            
             说明 
             | 
        
        
            | 
             spring-mock.jar 
             | 
        
        
            | 
             jwebunit-1.3.zip 
             | 
        
        
            | 
             httpunit-1.6.2.zip 
             | 
        
        
            | 
             junit-4.4.zip 
             | 
        
    
6.2. 目录结构 
将cas-client-2.0.11.zip解压后导入eclipse工程,目录结构如下:

6.3. 代码配置 
1、修改代码SecureURL.java,因数字签名只能使用只能是域名,而不能是IP之类的代替,故修改如下代码
edu.yale.its.tp.cas.util
    
        
            | 
             //URLConnection uc = u.openConnection(); 
             /** 
              * @sojust 
              * 由于hostname 只能是域名,而不能是IP之类的 屏蔽掉对hostname的校验  
              * http://forum.java.sun.com/thread.jspa?threadID=521779  
              * begin 
              */ 
                 HostnameVerifier hv = new HostnameVerifier() { 
                 public boolean verify(String urlHostName, SSLSession session) { 
                 System.out.println("Warning: URL Host: "+urlHostName+" vs."+session.getPeerHost()); 
                  return true; 
                   } 
                  }; 
              HttpsURLConnection.setDefaultHostnameVerifier(hv); 
              HttpsURLConnection uc= (javax.net.ssl.HttpsURLConnection)u.openConnection();  
                        //end 
             | 
        
    
2、修改Build.xml,将代码打包发布
    
        
            | 
              <target name="deploy"> 
              <mkdir dir="build"/> 
              <mkdir dir="build/META-INF"/> 
              <javac srcdir="src" 
               destdir="build"  
               deprecation="false" 
               classpathref="project.classpath" 
              />   
              <copy todir="build/META-INF"> 
               <fileset dir="conf"> 
                <include name="*"/> 
               </fileset> 
              </copy> 
              <jar jarfile="lib/casclient.jar" basedir="build"/> 
             </target> 
            <path id="project.classpath"> 
                     <path refid="lib.classpath" /> 
                 </path>  
                <path id="lib.classpath"> 
                     <fileset dir="lib" includes="*.jar" /> 
                 </path> 
             | 
        
    
7. PORTAL平台接入 
7.1. 资源介绍 
Liferay portal作为sso一个的客户端,使用Liferay-portal-cas-4.3.x.war进行配置比较简介,特别是4.0版本后的配置,其官网上有详细的说明介绍:
http://content.liferay.com/4.3/doc/installation/liferay_4_installation_guide/multipage/ch05s04.html
7.2. 代码配置 
修改portal-ext.properties ,如果系统中没有则创建一个portal-ext.properties ;打开portal-ext.properties并增加如下代码:
    
        
            | 
             cas.auth.enabled=true 
            cas.login.url=https://server IP:port/cas/login 
            cas.logout.url=https://server IP:port/cas/logout 
            cas.service.url=http:// client IP:port/portal/c/portal/login 
            cas.validate.url=https:// server IP:port/cas/proxyValidate 
             | 
        
    
配置完成后,测试client的portal,登录http:// client IP:port/portal/c/portal/login
(我的项目中增加/portal项目名称),系统会自动跳转至SSO登录界面,登录后会跳转回client的portal。登录成功!
8. 其它系统接入 
8.1. 子系统配置 
其它客户端子系统接入时需将提供的casclient.jar包烤入到应用"WEB-INF"lib 下,并进行相关配置。
8.2. wab.xml配置 
在wab中加入CASFilter,设置跳转过滤!
    
        
            | 
             <!-- CAS Filters --> 
            <filter> 
            <filter-name>CASFilter</filter-name> 
                     <filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class> 
            <init-param>             <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name> 
            <param-value>https://server IP:port/cas/login</param-value> 
            </init-param> 
            <!--这里的server是服务端的IP--> 
            <init-param> 
                         <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name> 
            <param-value>https://server IP:port/cas/proxyValidate</param-value> 
            </init-param> 
            <!--这里的serName是服务端的主机名--> 
            <init-param> 
                       <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name> 
            <param-value>client IP:port</param-value> 
            <!--client:port就是需要CAS需要拦截的地址和端口,一般就是这个启动的IP和port--> 
            </init-param> 
                      
            <init-param> 
            <param-name>needSession</param-name> 
            <param-value>1</param-value> 
            </init-param> 
            </filter> 
                 
            <filter-mapping> 
            <filter-name>CASFilter</filter-name> 
            <url-pattern>/*</url-pattern> 
            </filter-mapping> 
             | 
        
    
8.3. 接口开发 
在客户端的action中通过以下语句得到用户账号:
String userid = (String) ses.getAttribute(CASFilter.CAS_FILTER_USER);
从而编写用户认证,认证后请直接跳转到展示页面
具体应用举例:
使用struts进行用户登录跳转的使用如下方法进行开发:
Ø Struts action
    
        
            | 
             public ActionForward excuse(ActionMapping mapping, ActionForm form, 
               HttpServletRequest request, HttpServletResponse response) { 
             HttpSession ses = request.getSession();   
             String userid = (String) ses.getAttribute(CASFilter.CAS_FILTER_USER); 
            System.out.println(userid); 
            …… 
            return mapping.findForward("index");//您的展示面地址 
            } 
             | 
        
    
使用servlet进行页面登录跳转的:
Ø Servlet action
    
        
            | 
             public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
             HttpSession ses = request.getSession(); 
            String user = (String) ses.getAttribute(CASFilter.CAS_FILTER_USER); System.out.println(userid); 
            …… 
            String loginUrl =””;//您的展示面地址 
             response.sendRedirect(loginUrl); 
             } 
             | 
        
    
9. websphere配置 
Websphere6支持SSL双向认证,具体的安装认证步骤如下:
1、启动websphere;并查看端口。
Ws默认的端口是9060,web端口是9080,SSL端口是9443
2、配置SSL
在安全性—>SSl 进入SSL 配置指令表,修改DefaultSSLSettings中的密钥文件名及密码。
修改如下图所示:
密钥文件名为${USER_ROOT }/ keystore.jks.jks 
信任文件名为${USER_ ROOT }/keystore.jks.jks

3、修改完成后保存测试。
https://websphere ip:9443/ PlantsByWebSphere
(说明:一定要使用webspehre ip地址,与签证所使用的名字一至)

注意:使用webspehre 时将jks导入至ibm JDK的JVM,否则系统找不到相关密钥。