jasig CAS实现单点登录(数据库认证)

原创
2014/02/18 14:10
阅读数 5.3W

之前转载了一篇IBM的CAS单点登录实现,不过瘾,于是到官网弄下最新版本来再战一把:

这个CAS(Central Authentication Service)是耶鲁大学的开源项目,旨在实现企业应用单点登录,还是很不错的,牛b的大学确实不一样,不是我们这些2b学校式的教育。其官网http://www.jasig.org/cas,很不幸,应该翻了墙才能进去,自己去捣鼓翻墙吧,建议就GoAgent足已。

  • 实验环境:
1.jdk7_45
2.tomcat7_45
3.三台虚拟机:
   1.tomcat1(部署cas验证服务器)
   2.tomcat2(其中部署了两个web应用cas-web-client, cas-web-client2)
   3.mysql server一台(直接到数据库种验证)
  • 原理图:


  • 资源下载地址:

       http://downloads.jasig.org/

       解压之,jar会再modules目录下,其他都为源代码项目

       已经打包的server:

       client:

------------------------------------------------------

开始搭建:

  • CAS服务器配置:

1.在tomcat1所在机器生成证书:

这时会在用户主目录下生成.keystore文件,这个文件也可在上述命令种指定,其中生成过程会填入一些信息,注意输入第一个时(名字与姓氏)就输入你本机器的域名(不能时IP), 这里我的是www.tomcat1.com:

2.导出证书(后面将其导入客户端的jre环境中):

于是在用户主目录下就有了ssotest.crt证书文件(保留着,待会客户端配置要用),

3.配置Tomcat SSL: ${TOMCAT_HOME}/conf/server.xml中83-93行修改为:

<!-- Define a SSL HTTP/1.1 Connector on port 8443
   This connector uses the JSSE configuration, when using APR, the
   connector should be using the OpenSSL style configuration
   described in the APR documentation -->
<!-- configure ssl -->
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
         maxThreads="150" scheme="https" secure="true"
         clientAuth="false" sslProtocol="TLS"
         keystoreFile="/home/tomcatadmin/.keystore"
         keystorePass="ssotest"/>
4.将上面下载资源中的cas-server-webapp-3.5.2.war改名为cas.war, 复制到${TOMCAT_HOME}/webapps/下,启动tomcat,这时进入https://www.tomcat1.com:8443/cas/, 见下图,则服务端已经配置ok:

这时输入用户名及密码(保持一样就可以,默认CAS验证方式只要用户名密码一样就行), 可见其默认验证实现类SimpleTestUsernamePasswordAuthenticationHandler:

public final class SimpleTestUsernamePasswordAuthenticationHandler extends
    AbstractUsernamePasswordAuthenticationHandler {

    public boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) {
        final String username = credentials.getUsername();
        final String password = credentials.getPassword();

        if (StringUtils.hasText(username) && StringUtils.hasText(password)
            && username.equals(getPasswordEncoder().encode(password))) {//用户名及密码相同就成功
            return true;
        }
        return false;
    }
}

这样CAS服务端就默认配置完毕了,待会儿我们还要配置数据库验证。

  • 配置web客户端:

      1.生成.keystore(同上);

      2.将CAS服务端的导出ssotest.crt证书拷贝到某目录,并且导入到客户端机器的jre运行环境中:      

keytool -import -keystore $JAVA_HOME/jre/lib/security/cacerts -file ~/ssotest.crt -alias ssotest
# NOTE: 有可能会有异常:java.io.IOException: Keystore was tampered with, or password was incorrect. 那就先删除本机上述的cacerts文件。

       3.配置客户端Tomcat SSL(同上);

       4.新建WEB项目cas-web-client, 并加入依赖包:cas-client-core-3.2.1.jar,commons-logging-1.1.jar

       5.配置web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
    <display-name>cas-web-client2</display-name>
    <listener>
        <listener-class>
            org.jasig.cas.client.session.SingleSignOutHttpSessionListener
        </listener-class>
    </listener>
    <filter>
        <filter-name>CasSingleSignOutFilter</filter-name>
        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CasSingleSignOutFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
       <filter-name>CASFilter</filter-name>
       <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <init-param>
            <param-name>casServerLoginUrl</param-name><!-- Cas Server登录url-->
            <param-value>https://www.tomcat1.com:8443/cas/login</param-value>
        </init-param>
        <init-param><!-- 配置当前web应用所在的web服务器域名url -->
            <param-name>serverName</param-name>
            <param-value>http://www.tomcat2.com:8080</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CASFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>CasTicketFilter</filter-name>
        <filter-class>
            org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>https://www.tomcat1.com:8443/cas</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://www.tomcat2.com:8080</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CasTicketFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>CasRequestWrapFilter</filter-name>
        <filter-class>
            org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CasRequestWrapFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>AssertionThreadLocalFilter</filter-name>
        <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>AssertionThreadLocalFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

这样cas-web-client就完成了,拷贝一份为另一个web客户端cas-web-client2:


启动Cas Server所在tomcat(Tomcat1),再启动web客户端所在tomcat(Tomcat2),此时我们访问两个web客户端:

http://www.tomcat2.com:8080/cas-web-client/index.jsp

http://www.tomcat2.com:8080/cas-web-client2/index.jsp

都会被重定想到CAS Server登录界面,登录成功其中之一(将看到对应的index.jsp),再刷新另一个(也能看到对应的index.jsp了,因为已经登录过了), 这就算服务端和客户端都配置OK了。

------------------------------------------------------

  • 现在就是要定制我们自己的验证方式(基于数据库验证):

      1.新建WEB项目cas-auth-server,你需要将cas-server-webapp-3.5.2.war中的资源对应拷贝到项目中,再把下载包中cas-server-webapp的源码考到项目中,由于基于数据库验证,还得将cas-server-support-jdbc-3.5.2.jar和mysql-connector驱动包拷贝到WEB-INF/lib目录下,这样就构成了纯净的cas server项目,当然你也可以通过maven去构建,官网也有说明,如图:

      2.我们要做的是修改一些配置,就是WEB-INF/deployerConfigContext.xml文件,先配置mysql数据源:

<!-- DataSource,根据你的环境来定 -->
<bean id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource">
     <property name="driverClassName" value="com.mysql.jdbc.Driver" />
     <property name="url" value="jdbc:mysql://192.168.141.129:3306/blog?useUnicode=true&amp;characterEncoding=utf-8"/>
     <property name="username" value="mysqladmin" />
     <property name="password" value="mysqladmin" />
</bean>
      3.修改 authenticationManager bean的属性 authenticationHandlers:

<property name="authenticationHandlers">
    <list>				
        <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient" />
        <!--注释掉默认的的认证实现<bean 
        class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />-->
        <!-- 数据库查询认证处理器 -->
        <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
            <property name="dataSource" ref="mysqlDataSource"/>
            <property name="sql" 
                value="select password from t_user where username = ?" />
            <property name="passwordEncoder" ref="myPasswordEncoder"></property>
	</bean>			
    </list>
</property>

<!-- 自己定义的密码转译器,你可以自己定义,也可以用CAS提供的 -->
<bean id="myPasswordEncoder" class="org.jasig.cas.custom.encoder.MyPasswordEncoder" />


这样就配置完成了,将项目导出war包,并部署到tomcat1所在机器上运行起来,效果会之前一样。

收工。

展开阅读全文
打赏
6
83 收藏
分享
加载中
ihaolin博主

引用来自“uuhorse”的评论

跨域登录都不是什么难题,难点应该在于票据的管理,还有授权cookie的管理。
想知道CAS如何实现统一登出的,是各业务系统每次到CAS服务器验证票据吗,还是CAS登出的时候统一删除各业务系统域名下的Cookie?
如果各业务系统每次都验证票据,是不是对CAS的压力很大?
如果通过删除Cookie(或session),CAS怎么管理授权给这些子系统的票据(完全跨域的情况下)?
虽然现在并没有使用CAS来作统一session管理,但基本原理是将结合cookie中(会话ID)与后端的存储(如Redis集群)进行统一管理,在创建session时,为客户端生成一个(会话ID)存下来,下次客户端再来则从存储中获取对应的session,至于会话退出,只需将cookie中的会话ID失效并清空存储中对应的会话即可。
2015/10/06 22:43
回复
举报
跨域登录都不是什么难题,难点应该在于票据的管理,还有授权cookie的管理。
想知道CAS如何实现统一登出的,是各业务系统每次到CAS服务器验证票据吗,还是CAS登出的时候统一删除各业务系统域名下的Cookie?
如果各业务系统每次都验证票据,是不是对CAS的压力很大?
如果通过删除Cookie(或session),CAS怎么管理授权给这些子系统的票据(完全跨域的情况下)?
2015/08/12 16:47
回复
举报
ihaolin博主

引用来自“李泽平”的评论

做个一周免登陆,楼主有啥好的建议没
个人觉得是要结合cookie和CAS ticket失效时间配置。
2015/01/15 23:40
回复
举报
做个一周免登陆,楼主有啥好的建议没
2015/01/13 18:40
回复
举报
tomcat7.0.45这个版本,默认应该是apr方式吧,貌似博主的配置会报apr ssl配置的错误
2014/10/10 15:15
回复
举报

引用来自“小沫”的评论

希望能讲解下 cas server 原理
比方说
访问客户端时自动跳转到服务端去登陆,当登陆成功如何将Ticket返回给客户端。
还有就是 当退出的时候 服务端如何将客户端认证通过的信息 删除呢?
他们把这认证通过的信息是保存在 服务端 还是客户端 如果是客户端的话 是放在了Cookie?
http://wenku.baidu.com/view/0bcc0d01e87101f69e319595.html,觉得讲的还不错
2014/10/10 15:14
回复
举报
ihaolin博主

引用来自“小沫”的评论

希望能讲解下 cas server 原理
比方说
访问客户端时自动跳转到服务端去登陆,当登陆成功如何将Ticket返回给客户端。
还有就是 当退出的时候 服务端如何将客户端认证通过的信息 删除呢?
他们把这认证通过的信息是保存在 服务端 还是客户端 如果是客户端的话 是放在了Cookie?
你好,我在http://my.oschina.net/indestiny/blog/202454这篇文章里作了稍微详细点的讲述,不同版本可能实现差异比较,可以参见官方http://jasig.github.io/cas/4.0.0/index.html.
2014/10/09 19:58
回复
举报
希望能讲解下 cas server 原理
比方说
访问客户端时自动跳转到服务端去登陆,当登陆成功如何将Ticket返回给客户端。
还有就是 当退出的时候 服务端如何将客户端认证通过的信息 删除呢?
他们把这认证通过的信息是保存在 服务端 还是客户端 如果是客户端的话 是放在了Cookie?
2014/10/09 14:31
回复
举报
cas4.0后默认的密码验证不是简单的相同了。在配置文件里, 默认是 casuser:Mellon
2014/09/30 15:51
回复
举报
mark
2014/03/27 01:03
回复
举报
更多评论
打赏
10 评论
83 收藏
6
分享
返回顶部
顶部