使用 CAS 在 Tomcat 中实现单点登录(一)

单点登录(Single Sign On , 简称 SSO)是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。CAS(CentralAuthentication Service)是一款不错的针对 Web 应用的单点登录框架,本文介绍了 CAS 的原理、协议、在 Tomcat中的配置和使用,对于采用 CAS 实现轻量级单点登录解决方案的入门读者具有一定指导作用。

CAS介绍

CAS Yale大学发起的一个开源项目,旨在为 Web应用系统提供一种可靠的单点登录方法,CAS 2004 12月正式成为 JA-SIG的一个项目。CAS具有以下特点:

  • 开源的企业级单点登录解决方案。
  • CAS Server为需要独立部署的 Web应用。
  • CAS Client支持非常多的客户端(这里指单点登录系统中的各个 Web应用),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。

CAS原理和协议

从结构上看,CAS包含两个部分: CASServer CAS ClientCAS Server需要独立部署,主要负责对用户的认证工作;CAS Client负责处理对客户端受保护资源的访问请求,需要登录时,重定向到 CAS Server。图1 CAS最基本的协议过程:

1. CAS基础协议


CAS Client与受保护的客户端应用部署在一起,以 Filter方式保护受保护的资源。对于访问受保护资源的每个 Web请求,CAS Client会分析该请求的 Http请求中是否包含 Service Ticket,如果没有,则说明当前用户尚未登录,于是将请求重定向到指定好的 CAS Server登录地址,并传递 Service(也就是要访问的目的资源地址),以便登录成功过后转回该地址。用户在第 3步中输入认证信息,如果登录成功,CAS Server随机产生一个相当长度、唯一、不可伪造的 Service Ticket,并缓存以待将来验证,之后系统自动重定向到 Service所在地址,并为客户端浏览器设置一个 Ticket Granted CookieTGC),CAS Client 在拿到 Service和新产生的 Ticket过后,在第 56步中与 CASServer进行身份合适,以确保 Service Ticket的合法性。

在该协议中,所有与CAS的交互均采用 SSL协议,确保,ST TGC的安全性。协议工作过程中会有 2次重定向的过程,但是 CAS Client CAS Server之间进行 Ticket验证的过程对于用户是透明的。

另外,CAS协议中还提供了Proxy(代理)模式,以适应更加高级、复杂的应用场景,具体介绍可以参考 CAS官方网站上的相关文档。

准备工作

本文中的例子以tomcat5.5为例进行讲解,下载地址:

http://tomcat.apache.org/download-55.cgi

CAS官方网站下载 CASServer Client,地址分别为:

http://www.ja-sig.org/downloads/cas/cas-server-3.1.1-release.zip

http://www.ja-sig.org/downloads/cas-clients/cas-client-java-2.1.1.zip

回页首

部署 CAS Server

CAS Server是一套基于 Java实现的服务,该服务以一个 Java Web Application单独部署在与 servlet2.3兼容的 Web服务器上,另外,由于Client CAS Server之间的交互采用 Https协议,因此部署 CAS Server的服务器还需要支持 SSL协议。当 SSL配置成功过后,像普通 Web应用一样将 CAS Server部署在服务器上就能正常运行了,不过,在真正使用之前,还需要扩展验证用户的接口。

Tomcat上部署一个完整的 CASServer主要按照以下几个步骤:

配置 Tomcat使用Https协议

如果希望 Tomcat支持 Https,主要的工作是配置SSL协议,其配置过程和配置方法可以参考 Tomcat的相关文档。不过在生成证书的过程中,会有需要用到主机名的地方,CAS建议不要使用 IP地址,而要使用机器名或域名。

部署 CAS Server

CAS Server是一个 Web应用包,将前面下载的 cas-server-3.1.1-release.zip解开,把其中的cas-server-webapp-3.1.1.war拷贝到 tomcat webapps目录,并更名为 cas.war。由于前面已配置好 tomcat https协议,可以重新启动 tomcat,然后访问:https://localhost:8443/cas,如果能出现正常的 CAS登录页面,则说明 CAS Server已经部署成功。

虽然 CASServer已经部署成功,但这只是一个缺省的实现,在实际使用的时候,还需要根据实际概况做扩展和定制,最主要的是扩展认证 (Authentication)接口和 CAS Server的界面。

扩展认证接口

CAS Server负责完成对用户的认证工作,它会处理登录时的用户凭证 (Credentials)信息,用户名/密码对是最常见的凭证信息。CAS Server可能需要到数据库检索一条用户帐号信息,也可能在 XML文件中检索用户名/密码,还可能通过 LDAP Server获取等,在这种情况下,CAS提供了一种灵活但统一的接口和实现分离的方式,实际使用中 CAS采用哪种方式认证是与 CAS的基本协议分离开的,用户可以根据认证的接口去定制和扩展。

扩展 AuthenticationHandler

CAS提供扩展认证的核心是 AuthenticationHandler接口,该接口定义如清单 1下:

清单 1. AuthenticationHandler定义

public interfaceAuthenticationHandler {
    /**
     * Method to determine if thecredentials supplied are valid.
     * @param credentials The credentialsto validate.
     * @return true if valid, returnfalse otherwise.
     * @throws AuthenticationException AnAuthenticationException can contain
     * details about why a particularauthentication request failed.
     */
    boolean authenticate(Credentials credentials)throws AuthenticationException;
/**
     * Method to check if the handlerknows how to handle the credentials
     * provided. It may be a simple checkof the Credentials class or something
     * more complicated such as scanningthe information contained in the
     * Credentials object.
     * @param credentials The credentialsto check.
     * @return true if the handlersupports the Credentials, false othewrise.
     */
    boolean supports(Credentialscredentials);
}

该接口定义了 2个需要实现的方法,supports()方法用于检查所给的包含认证信息的Credentials是否受当前 AuthenticationHandler支持;而 authenticate()方法则担当验证认证信息的任务,这也是需要扩展的主要方法,根据情况与存储合法认证信息的介质进行交互,返回 boolean类型的值,true表示验证通过,false表示验证失败。

CAS3中还提供了对AuthenticationHandler接口的一些抽象实现,比如,可能需要在执行authenticate()方法前后执行某些其他操作,那么可以让自己的认证类扩展自清单 2中的抽象类:

清单 2. AbstractPreAndPostProcessingAuthenticationHandler定义

public abstract classAbstractPreAndPostProcessingAuthenticationHandler
                                          implements AuthenticateHandler{
    protected Log log =LogFactory.getLog(this.getClass());
    protected booleanpreAuthenticate(final Credentials credentials) {
        return true;
    }
    protected booleanpostAuthenticate(final Credentials credentials,
        final boolean authenticated){
        return authenticated;
    }
    public final booleanauthenticate(final Credentials credentials)
        throws AuthenticationException{
        if(!preAuthenticate(credentials)) {
            return false;
        }
        final boolean authenticated =doAuthentication(credentials);
        returnpostAuthenticate(credentials, authenticated);
    }
    protected abstract booleandoAuthentication(final Credentials credentials)
throws AuthenticationException;
}

AbstractPreAndPostProcessingAuthenticationHandler类新定义了preAuthenticate()方法和 postAuthenticate()方法,而实际的认证工作交由doAuthentication()方法来执行。因此,如果需要在认证前后执行一些额外的操作,可以分别扩展 preAuthenticate() ppstAuthenticate()方法,而doAuthentication()取代 authenticate()成为了子类必须要实现的方法。

由于实际运用中,最常用的是用户名和密码方式的认证,CAS3提供了针对该方式的实现,如清单 3所示:

清单 3. AbstractUsernamePasswordAuthenticationHandler定义

public abstract classAbstractUsernamePasswordAuthenticationHandler extends
                      AbstractPreAndPostProcessingAuthenticationHandler{
...
 protected final booleandoAuthentication(final Credentials credentials)
 throws AuthenticationException{
 returnauthenticateUsernamePasswordInternal((UsernamePasswordCredentials)credentials);
 }
 protected abstract booleanauthenticateUsernamePasswordInternal(
        final UsernamePasswordCredentialscredentials) throws AuthenticationException;  
protected final PasswordEncoder getPasswordEncoder() {
 return this.passwordEncoder;
 }
public final void setPasswordEncoder(final PasswordEncoder passwordEncoder){
 this.passwordEncoder =passwordEncoder;
    }
...
}

基于用户名密码的认证方式可直接扩展自 AbstractUsernamePasswordAuthenticationHandler,验证用户名密码的具体操作通过实现 authenticateUsernamePasswordInternal() 方法达到,另外,通常情况下密码会是加密过的,setPasswordEncoder()方法就是用于指定适当的加密器。

从以上清单中可以看到,doAuthentication()方法的参数是 Credentials类型,这是包含用户认证信息的一个接口,对于用户名密码类型的认证信息,可以直接使用 UsernamePasswordCredentials,如果需要扩展其他类型的认证信息,需要实现Credentials接口,并且实现相应的 CredentialsToPrincipalResolver 接口,其具体方法可以借鉴UsernamePasswordCredentials UsernamePasswordCredentialsToPrincipalResolver

JDBC认证方法

用户的认证信息通常保存在数据库中,因此本文就选用这种情况来介绍。将前面下载的 cas-server-3.1.1-release.zip包解开后,在modules目录下可以找到包 cas-server-support-jdbc-3.1.1.jar,其提供了通过 JDBC连接数据库进行验证的缺省实现,基于该包的支持,我们只需要做一些配置工作即可实现 JDBC 认证。

JDBC认证方法支持多种数据库,DB2, Oracle, MySql, Microsoft SQL Server等均可,这里以 DB2作为例子介绍。并且假设DB2数据库名:CASTest,数据库登录用户名: db2user,数据库登录密码: db2password,用户信息表为: userTable,该表包含用户名和密码的两个数据项分别为 userName password

1. 配置 DataStore

打开文件%CATALINA_HOME%/webapps/cas/WEB-INF/deployerConfigContext.xml,添加一个新的 bean标签,对于 DB2,内容如清单 4所示:

清单 4.配置 DataStore

<beanid="casDataSource"class="org.apache.commons.dbcp.BasicDataSource">
     <propertyname="driverClassName">
          <value>com.ibm.db2.jcc.DB2Driver</value>
     </property>
     <propertyname="url">
         <value>jdbc:db2://9.125.65.134:50000/CASTest</value>
     </property>
     <propertyname="username">
         <value>db2user</value>
     </property>
     <propertyname="password">
         <value>db2password</value>
     </property>
</bean>

其中 id属性为该DataStore的标识,在后面配置 AuthenticationHandler会被引用,另外,需要提供 DataStore所必需的数据库驱动程序、连接地址、数据库登录用户名以及登录密码。

2.配置 AuthenticationHandler

cas-server-support-jdbc-3.1.1.jar包中,提供了 3个基于 JDBC AuthenticationHandler,分别为BindModeSearchDatabaseAuthenticationHandler,QueryDatabaseAuthenticationHandler,SearchModeSearchDatabaseAuthenticationHandler。其中BindModeSearchDatabaseAuthenticationHandler是用所给的用户名和密码去建立数据库连接,根据连接建立是否成功来判断验证成功与否;QueryDatabaseAuthenticationHandler通过配置一个 SQL语句查出密码,与所给密码匹配;SearchModeSearchDatabaseAuthenticationHandler通过配置存放用户验证信息的表、用户名字段和密码字段,构造查询语句来验证。

使用哪个AuthenticationHandler,需要在 deployerConfigContext.xml中设置,默认情况下,CAS使用一个简单的 username=password AuthenticationHandler,在文件中可以找到如下一行:<beanclass="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePassword

AuthenticationHandler" />,我们可以将其注释掉,换成我们希望的一个 AuthenticationHandler,比如,使用QueryDatabaseAuthenticationHandlerSearchModeSearchDatabaseAuthenticationHandler可以分别选取清单 5或清单 6的配置。

清单 5.使用QueryDatabaseAuthenticationHandler

<beanclass="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
 <property name="dataSource"ref=" casDataSource " />
 <property name="sql"
       value="select password fromuserTable where lower(userName) = lower(?)" />
</bean>

清单 6.使用SearchModeSearchDatabaseAuthenticationHandler

<beanid="SearchModeSearchDatabaseAuthenticationHandler"
     class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler"
      abstract="false"singleton="true" lazy-init="default"
                      autowire="default"dependency-check="default">
  <property  name="tableUsers">
  <value>userTable</value>
  </property>
  <propertyname="fieldUser">
  <value>userName</value>
  </property>
  <propertyname="fieldPassword">
  <value>password</value>
  </property>
  <propertyname="dataSource" ref=" casDataSource "/>
</bean>

另外,由于存放在数据库中的密码通常是加密过的,所以 AuthenticationHandler在匹配时需要知道使用的加密方法,在deployerConfigContext.xml文件中我们可以为具体的 AuthenticationHandler类配置一个 property,指定加密器类,比如对于QueryDatabaseAuthenticationHandler,可以修改如清单7所示:

清单 7.添加passwordEncoder

<beanclass="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
  <propertyname="dataSource" ref=" casDataSource " />
  <property name="sql"
           value="select passwordfrom userTable where lower(userName) = lower(?)" />
  <property  name="passwordEncoder" ref="myPasswordEncoder"/>
</bean>

其中myPasswordEncoder是对清单 8中设置的实际加密器类的引用:

清单 8.指定具体加密器类

<beanid="passwordEncoder"
           class="org.jasig.cas.authentication.handler.MyPasswordEncoder"/>

这里MyPasswordEncoder是根据实际情况自己定义的加密器,实现 PasswordEncoder接口及其 encode()方法。



参考:http://www.ibm.com/developerworks/cn/opensource/os-cn-cas/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值