`
wang5598
  • 浏览: 112883 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

CAS单点登陆部署

 
阅读更多

这阵子在研究yale大学的jasig项目下面的CAS单点登陆系统(项目地址是:http://www.jasig.org/cas),经过一周的测试,整个安装部署都已经成功了,现在将部署过程记录如下:

 

一、准备工作:

装好JDK(1.6),Tomcat(6.0),下载CAS服务端和客户端(cas-server-3.4.11-release和cas-client-3.2.1-release,这两个版本是目前最新的,下载地址是:http://www.jasig.org/cas_server_3_4_11_release)。

 

二、设置证书:

生成服务端的证书,这里和其它教程一样采用的都是JDK所自带的keytool工具:

1).生成证书(server端):
keytool -genkey -alias mycas -keyalg RSA -keystore d:\keys\mycas.keystore;
2.导出证书(server端):
keytool -export -trustcacerts -file d:\keys\mycas.crt -alias mycas -keystore d:\keys\mycas.keystore
3.查看证书(client端,即存放子应用的机器,我这里以windows演示):
(首先进入JDK目录 cd C:\Program Files\Java\jdk1.6.0_10\jre\lib\security)  keytool -list -keystore cacerts
4.导入证书(client端,为方便演示,我在client的D盘下也建了这个目录,然后把crt文件放进去了):
keytool -import -trustcacerts -keystore cacerts -file d:\keys\mycas.crt -alias mycas -storepass changeit
 5.删除证书(client端,不是必须的操作,这里只是列出来,需要删除的时候才用的):
keytool -delete -trustcacerts -alias mycas -keystore cacerts -storepass changeit

 

 

 

 

 

三、开启服务端Tomcat的SSL连接服务,确保Tomcat所用的JDK和之前所装的JDK是相同的(有的eclipse中的tomcat是用的eclipse自带的jdk的,这个要区分好的)。

修改Tomcat的conf下面server.xml文件,去掉以下代码的注释,然后添加你自己的keystore.
 <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
               maxThreads="150" scheme="https" secure="true" 
               clientAuth="false" sslProtocol="TLS"
               keystoreFile="d:\keys\mycas.keystore"  
               keystorePass="你的密码"
    />

 

四、设置服务端配置文件。首先将cas-server-3.4.11解压后,复制modules下面的cas-server-webapp-3.4.11.war到tomcat的webapp下面(手动解压或者启动tomcat解压)。启动tomcat后,就可以在地址栏,以https://wangyq(我自己的计算机名):8443/cas/ 来进行访问了.



 

cas的配置文件在deployerConfigContext.xml中默认的登陆验证方式是SimpleTestUsernamePasswordAuthenticationHandler,也就是用户名和密码一致就可以登陆;我们通常需要从数据库中取出用户名和密码进行验证,所以我们需要修改deployerConfigContext.xml,配置我们自己的服务认证方式:首先在deployerConfigContext.xml配置我们数据源,在<sec:user-service id="userDetailsService">这个节点后面添加casDataSource:

<bean id="casDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName">
	<value>oracle.jdbc.driver.OracleDriver</value>
    </property>
    <property name="url">
	<value>jdbc:oracle:thin:@10.0.12.67:1521:orcl</value>
    </property>    
    <property name="username">
	<value>username</value>    
    </property>
    <property name="password">
	<value>yourpassword</value>
    </property>
</bean>

 

然后注释掉SimpleTestUsernamePasswordAuthenticationHandler,添加QueryDatabaseAuthenticationHandler:

<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
   <property name="dataSource" ref="casDataSource" />
   <property name="sql" value="select password from userinformation where username = ?" /> 
</bean>

 说明:默认的它是不带数据库的驱动的,要自己把相应的数据库驱动程序放到cas的lib下面,我这里需要的ojdbc.jar.

 

五、配置客户端, 简单点就是把官方提供的客户端的jar加入到第三方应用的项目中,然后在第三方应用的web.xml中配置好对应的过滤器即可了。我这里把我的cas-client-core-3.2.1.jar这个包直接加入到我的第三方应用的lib下面了,然后在web.xml中加上过滤器的配置:

<!-- ======================== 单点登录开始 ======================== -->
        <!-- 用于单点退出,该过滤器用于实现单点登出功能,可选配置-->
        <listener>
                <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
        </listener>

        <!-- 该过滤器用于实现单点登出功能,可选配置。 -->
        <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>/*</url-pattern>
        </filter-mapping>

        <!-- 该过滤器负责用户的认证工作,必须启用它;serverName中填写第三方应用所在服务器的连接地址,注意不要出现localhost或者127.0.0.1,不然会出现无法同步登出的问题  -->
        <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://wangyq:8443/cas/login</param-value>
                        <!--这里的server是服务端的IP-->
                </init-param>
                <init-param>
                        <param-name>serverName</param-name>
                        <param-value>http://192.168.5.100:8080</param-value>
                </init-param>
        </filter>
        <filter-mapping>
                <filter-name>CASFilter</filter-name>
                <url-pattern>/*</url-pattern>
        </filter-mapping>

        <!-- 该过滤器负责对Ticket的校验工作,必须启用它;serverName中填写第三方应用所在服务器的连接地址,注意不要出现localhost或者127.0.0.1,不然会出现无法同步登出的问题 -->
        <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://wangyq:8443/cas</param-value>
                </init-param>
                <init-param>
                        <param-name>serverName</param-name>
                        <param-value>http://192.168.5.100: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>
        
        <!-- 自动根据单点登录的结果设置本系统的用户信息 -->
        <filter>
                <display-name>AutoSetUserAdapterFilter</display-name>
                <filter-name>AutoSetUserAdapterFilter</filter-name>
                <filter-class>cn.util.AutoSetUserAdapterFilter</filter-class>
        </filter>
        <filter-mapping>
                <filter-name>AutoSetUserAdapterFilter</filter-name>
                <url-pattern>/*</url-pattern>
        </filter-mapping>
        <!-- ======================== 单点登录结束 ======================== -->

 然后附上AutoSetUserAdapterFilter这个过滤器的代码:

package cn.util;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.jasig.cas.client.validation.Assertion;
import cn.domain.UserInformation;

/**
 * CAS单点登陆的过滤器功能类,该类用来自动生成子应用的登陆Session
 * 
 */
public class AutoSetUserAdapterFilter  implements Filter {
	
    /**
     * Default constructor. 
     */
    public AutoSetUserAdapterFilter() {
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
    }

   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
                   ServletException {
           HttpServletRequest httpRequest = (HttpServletRequest) request;
           
           // _const_cas_assertion_是CAS中存放登录用户名的session标志
           Object object = httpRequest.getSession().getAttribute("_const_cas_assertion_");
           
           if (object != null) {
                   Assertion assertion = (Assertion) object;
                   String loginName = assertion.getPrincipal().getName();
                   UserInformation user = UserUtil.getCurrentUser(httpRequest);
                   
                   // 第一次登录系统
                   if (user == null) {
                	   user = cn.util.CommomMethod.getUserBean(loginName);
                           // 保存用户信息到Session
                          UserUtil.saveUserToSession(user,httpRequest);
                   }
                   
           }
          	chain.doFilter(request, response);
   }

	   /**
	    * @see Filter#init(FilterConfig)
	    */
	   public void init(FilterConfig fConfig) throws ServletException {
	   }
		
}

 UserUtil就是一个简单的操作用户登录session的一个工具类,代码如下:

package cn.util;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import cn.domain.UserInformation;

/**
 * 该类被用来保存、获取、删除用户的SessionBean信息
 * @author WangYQ
 *
 */
public class UserUtil{
	 /**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
     *      用户的Session标志
     */
    public static String USER = "ui";
    /**
     *      已登录的用户
     */
    public static Map<String, UserInformation> loginUsers = new HashMap<String, UserInformation>();

    /**
     * 保存用户信息到Session
     * @param user
     */
    public static void saveUserToSession(UserInformation user,HttpServletRequest httpRequest) {
    	httpRequest.getSession().setAttribute("ui", user);
    }

    /**
     * 获取当前登录的用户
     * @return
     */
    public static UserInformation getCurrentUser(HttpServletRequest httpRequest) {
    	HttpSession session = httpRequest.getSession();
    	if(session!=null){
    		Object sessionUser  = session.getAttribute("ui");
    		if(sessionUser == null){
    			return null;
    		}
    		UserInformation user =  (UserInformation) sessionUser;
    		return user;
    	}else{
    		return null;
    	}
    }

    /**
     * 获取当前用户的帐号
     * @return 当前用户的帐号
     */
    public static String getCurrentUserName(HttpServletRequest httpRequest) {
    	Object sessionUser = getCurrentUser(httpRequest);
    	if(sessionUser==null){
    		return "";
    	}else{
    		UserInformation user =  (UserInformation) sessionUser;
    		return user.getUsername();
    	}
    }

    /**
     * 从session中移除用户
     */
    public static void removeUserFromSession(HttpServletRequest httpRequest) {
    	httpRequest.getSession().removeAttribute("ui");
    }
}

 

 CommomMethod.getUserBean这也是一个工具类中根据用户帐号获取用户信息bean的一个方法,为了演示我简化下代码:

package cn.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.util.ServletContextAware;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import com.opensymphony.xwork2.ActionContext;
import cn.domain.UserInformation;
import cn.service.SessionService;
import cn.domain.UserInformation;

public class CommomMethod {
	
	private static JdbcTemplate template ;
	//其它的业务代码省略	
	public static UserInformation getUserBean(String username){
		UserInformation UI = new UserInformation();
		int type = 1;
        String uname="",upass="";
        SqlRowSet rs =null;
        template = HibernateSessionFactory.gettemplate();
        String hsql = "select username,password,type,realname,roletype,schoolname,school_id,role_name,avatarurl,isupdate from userinformation where username='"+username+"'";
        rs = template.queryForRowSet(hsql);
        while(rs.next()){
        	uname  = rs.getString(1);
        	upass   =  rs.getString(2);
        	type = rs.getInt(3);
        	UI.setUsername(uname);
        	UI.setPassword(upass);
        	UI.setType(type);
        	UI.setRealname(rs.getString("realname"));
        	UI.setRoletype(rs.getInt("roletype"));
        	UI.setSchoolname(rs.getString("schoolname"));
        	UI.setSchool_id(rs.getInt("school_id"));
        	UI.setRolename(rs.getString("role_name"));
        	UI.setAvatarurl(rs.getString("avatarurl"));
        	UI.setUpdate(rs.getString("isupdate").equals("1"));
        }
		return UI;
	}
}

 UserInformation 就是一个简单的javabean存放的用户的一些基本属性,我这里是直接使用的jdbctemplate,如果你使用的是hibernate的话,可以自行变更获取方法;

 

六、最后一步,就是把由服务端生成的证书导入到第三方应用所在服务器的JDK的受信任的证书列表中,详细的可以看第二步骤中的第四小点,需要说明的是,要在cmd中首先进入到jdk的目录中(cd C:\Program Files\Java\jdk1.6.0_10\jre\lib\security),然后再导入操作。那至此全部操作就已经完成了,导入证书完成后,分别启动服务端cas和客户端的应用,就能实现自己的单点登陆和单点登出了。

 

 总结一点:CAS的单点登陆安装和配置我已经成功完成了,目前对代码的研究还没开始,只是处在一个逻辑流程的熟悉阶段,感觉其实最主要的工作还是在客户端,通过过滤器把所有的对于第三方应用的未登录访问全部指向到cas的server进行验证,验证成功后再把地址redirect到先前的service上面。

 

写这篇文章,参考了很多别人的东西,这里推荐两个教程:

http://www.wsria.com/archives/1349(咖啡兔,写的很详细,我开始也是参照着来做的)

http://wenku.baidu.com/view/a2352819227916888486d7e8.html(百度文库,一些细节写的很详细)

 

最后新年第一天报道,祝大家龙年龙马精神,步步高升,呵呵~

 

  • 大小: 73.6 KB
  • 大小: 15.7 KB
  • 大小: 55.2 KB
  • 大小: 137.1 KB
分享到:
评论
3 楼 焦志广 2013-09-12  
启动tomcat
java.lang.Exception: Connector attribute SSLCertificateFile must be defined when using SSL with APR
at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:507)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:610)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:429)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:981)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:814)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.startup.Catalina.load(Catalina.java:640)
at org.apache.catalina.startup.Catalina.load(Catalina.java:665)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
2 楼 wang5598 2012-05-07  
有没有详细的报错信息? CAS Server的包中本来就没有这个common_rosters.js的呀——!
1 楼 xucaishen 2012-04-26  
3.4.11部署后测试无法登录,而且报common_rosters.js文件不存在错误.
换回3.4.7后成功登录,common_rosters.js文件不存在错误还是有.

相关推荐

    改造CAS单点登录部署文件

    在这个主题中,我们将深入探讨如何改造CAS单点登录部署文件,以及涉及到的相关知识点。 首先,"cas.war"是一个Web应用的归档文件,通常由Java的Web应用程序(Web Application)打包而成。当你在服务器上部署这个...

    基于Java集成CAS单点登录【接部署即可启用】

    基于Java中CAS的单点登录,有服务端的所有源码,将tomcat目录下的所有资源直接拷到Tomcat服务中间件的webapp目录下,阅读tomcat-webapp中的read.txt文档,查看使用说明,适用于第一次开发CAS单点登录的同学们,简单...

    CAS单点登录操作文档

    CAS单点登录操作文档 CAS 是 Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。CAS 具有以下特点: • 开源的企业级单点登录解决...

    CAS单点登录demo

    在本“CAS单点登录demo”中,我们将深入探讨CAS的工作原理、配置步骤以及如何实现客户端与服务器端的交互。 1. CAS工作原理: CAS的核心思想是集中式的身份验证,用户只需在一个地方进行登录,之后访问其他已经...

    CAS单点登录实例

    本文将深入探讨CAS单点登录实例及其相关知识点。 首先,单点登录(Single Sign-On,SSO)是一种身份验证机制,使得用户在一个应用系统中登录后,无需再次输入认证信息即可访问其他关联的应用系统。CAS作为开源的SSO...

    使用CAS整合CXF实现单点登录部署步骤

    本文将详细介绍如何使用CAS整合CXF,实现基于Tomcat服务器的单点登录部署步骤。 首先,我们需要在Tomcat服务器上部署CAS项目。这通常涉及以下步骤: 1. **下载CAS服务器**:从官方Git仓库或Maven仓库获取最新的CAS...

    cas单点登录

    总之,CAS单点登录系统提供了统一的身份验证入口,简化了用户登录过程,提高了用户体验。通过理解和实践CAS Server的配置以及客户端的集成,开发者可以有效地在自己的应用环境中实现单点登录功能。

    CAS单点登录配置

    在提供的PDF文件`cas单点登录(一).pdf`和`cas单点登录(二).pdf`中,应该详细涵盖了这些步骤,以及更深入的技术细节,包括可能出现的问题和解决方案。通过学习这些文档,你应该能够成功地配置和实施CAS单点登录...

    .net cas单点登录

    这个项目可能包含配置文件、控制器代码、视图模板和其他相关资源,展示了如何在实际应用中实现CAS单点登录功能。 综上所述,.NET CAS单点登录涉及到了身份验证、票证机制、客户端和服务器之间的交互等多个核心概念...

    CAS整合LDAP实现单点登录原理及部署

    CAS整合LDAP实现单点登录的原理及部署学习笔记,cas实现单点登录,ldap负责账户管理

    cas单点登录服务端

    CAS(Central Authentication ...总的来说,CAS单点登录服务端的部署涉及了Web应用的部署、应用服务器的管理、服务定义配置、用户认证集成以及安全性考量等多个方面,是构建安全、便捷的多应用系统环境的关键组件。

    CAS单点登录例子,包含服务端和客户端

    综上所述,这个压缩包提供了一个完整的CAS单点登录实例,包括服务端和客户端的实现,可以帮助开发者理解并部署自己的CAS系统。通过深入研究和实践,你可以掌握如何利用CAS实现Web应用的安全、便捷的单点登录功能。

    CAS单点登录配置大全

    **CAS单点登录配置大全** CAS(Central Authentication Service,中央认证服务)是一种广泛使用的开源单点登录(Single Sign-On,SSO)协议。它允许用户通过一个统一的认证系统访问多个应用系统,而无需在每个系统...

    基于Cas的单点登录实现

    **基于Cas的单点登录实现** 单点登录(Single Sign-On,简称SSO)是一种在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统的技术。它为用户提供了一种方便、高效的访问多系统的方式,同时减少...

    CAS单点登陆资料学习单点登陆

    CAS单点登录的核心工作流程如下: 1. **用户访问受保护的应用**:用户尝试访问第一个受CAS保护的Web应用时,会被重定向到CAS服务器的登录页面。 2. **CAS服务器的重定向**:如果用户尚未登录,CAS服务器会显示登录...

    用cas实现mantis单点登录和登出

    ### 使用 CAS 实现 Mantis 单点登录与登出 #### 概述 单点登录(Single Sign-On,简称 SSO)是一种常见的身份认证模式,它允许用户在多个应用程序和服务中仅通过一次登录就能访问所有相关系统而无需多次输入密码。...

    struts2+spring+cas单点登录

    使用struts2+spring+cas实现的单点登录功能,里面包括cas-server3.5.2项目一个,cas-client3.2.1 web项目两个,数据库脚本,请按照里面的说明文档进行部署,希望你们也能配置成功。

    CAS单点登录多语言整合文档+源码

    这个压缩包文件包含的是关于CAS单点登录的多语言整合文档和源码,特别提到了PHP客户端和Java客户端的整合。 首先,我们来深入理解一下CAS的基本工作原理。当用户尝试访问受CAS保护的应用时,会被重定向到CAS服务器...

    CAS单点登录配置全过程

    本文将详细介绍CAS单点登录的基本配置过程,虽然文中提到的配置较为简单,但涵盖了CAS部署的核心步骤。请注意,此教程并未涉及复杂的验证机制或MD5校验等安全措施,因此仅适用于测试环境。 #### 二、准备工作 1. *...

    java-cas单点登录服务端

    CAS(Central Authentication Service)是一款不错的针对 Web 应用的单点登录框架,本文介绍了 CAS 的原理、协议、在 Tomcat 中的配置和使用,研究如何采用 CAS 实现轻量级单点登录解决方案。 CAS 是 Yale 大学发起的...

Global site tag (gtag.js) - Google Analytics