单点登录解决方案:CAS

来源:互联网 发布:爱回收 知乎 编辑:程序博客网 时间:2024/06/06 09:59

CAS单点登录基本原理

当用户第一次访问CASClient应用时,应用会根据部署的CASAuthentication Filter过滤器将请求重定向到CASServer,同时生成service参数,类似如下URL

http(s)://cas_server/cas/login?service=http(s)://other_server/application1

    当CASServer收到请求之后,判断该用户是否已存在有效的Ticket Granting Ticket(TGT),并进行认证。如果认证成功,CASServer会生成一个Service Ticket(ST),同时会将ticket参数附加在URL之后返回,类似如下URL:

http(s)://other_server/application1?ticket=ST-8670-123buTvFFjo980

    之后应用会根据部署的CAS Validation Filter过滤器连接到CASServer校验ticket的有效性。

 

CAS单点登录认证过程时序图如下:

 

CASServer安装部署

配置服务器端数字证书

由于CAS要求ClientServer之间的通信以https协议进行,所以需要在服务器端生成相应的数字证书。

1.        生成数字证书,注意生成数字证书是必须使用主机名或者域名来定义证书名称(CN

keytool -genkey-alias castest -keypass changeit -keyalg RSA -keystore ~/server.keystore

例如:cas.testserver.comCN=cas.testserver.comOU=testserverO=testserverL=ShanghaiST=ShanghaiC=China

2.        导出数字证书

keytool -export-alias castest -keypass changeit -keyalg RSA -keystore ~/server.keystore -file~/castest.cer

3.        将数字证书导入jre的可信区

keytool -import-alias castest -keypass changeit -keystore ./jre/lib/security/cacerts -file~/castest.cer

4.        查看证书是否加入成功

keytool -list -alias castest -keypass changeit -keystore$JAVA_HOME/jre/lib/security/cacerts

配置CASServer以支持SSL

Tomcat6.0为例,修改server.xml,修改以下配置:

 

<Connector port="8443"protocol="HTTP/1.1" SSLEnabled="true"

               maxThreads="150"scheme="https" secure="true"

               clientAuth="false"sslProtocol="TLS"

              keystoreFile="/root/server.keystore"

              keystorePass="changeit"

              truststoreFile="$JAVA_HOME/jre/lib/security/cacerts"

     />

部署CASServer应用

CASServer应用是以war包的形式提供,具体部署过程和其他Web应用无异,这里不再详细描述。

 

认证方式的管理

CASServer自身提供的多种认证方式的实现,包括:JAASJDBCLDAPLegacy等,可以通过附加jar包的方式进行实现。以下以JDBC为例进行说明:

1.        CASServerJDBC认证方式的扩展jar包上传至CASServer/WEB-INF/lib/目录下,jar包获取地址如下:

svn://192.168.3.17/BSTPRJ/BSTBOSS-V1.0/2-SRC/02-Branch/cas-server-3.4.11/modules/cas-server-support-jdbc-3.4.11.jar

2.        确保CASServer应用中已经包含所需的jdbc驱动程序,如果没有,也需要上传

3.        修改WEB-INF/cas.properties中的数据库相关配置,如下:

 

 

db.driver=oracle.jdbc.driver.OracleDriver

db.url=jdbc:oracle:thin:@192.168.1.222:1521:Ora10_TeleBusiness

db.username=uap

db.password=bstadmin

 

 

4.        同时可以通过修改WEB-INF/deployerConfigContext.xml的方式来配置所需信息,具体如下:

找到<property name="authenticationHandlers">标签

注释原默认认证处理器

 

<!-- 

         <bean

         class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler"  />

-->

 

添加JDBC认证处理器,

 

<bean  class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">

                                               <property name="sql" value="select password from tb_user where username=?" />

                                               <property  name="passwordEncoder" ref="passwordEncoder"/>

                                               <property  name="dataSource" ref="dataSource" />

                                     </bean>  

 

5.        添加dataSource相关配置

WEB-INF/deployerConfigContext.xml末尾添加dataSource配置

 

<!-- Data source definition  --> 

     <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource"  destroy-method="close">    

              <property  name="driverClassName">      

                        <value>${db.driver}</value>   

              </property>   

              <property  name="url">     

                        <value>${db.url}</value>   

              </property>   

              <property name="username"><value>${db.username}</value></property>   

              <property  name="password"><value>${db.password}</value></property> 

     </bean>

 

 

6.        添加passwordEncoder相关配置

WEB-INF/ deployerConfigContext.xml末尾添加passwordEncoder配置

 

<!-- Password Encoder  definition -->

         <bean  id="passwordEncoder"  class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder"  p:characterEncoding="UTF-8" >    

              <constructor-arg  index="0" value="MD5" />

    </bean>

 

 

CASClient安装部署

配置CASClient中的数字认证

1.        将证书文件上传到CASClient服务器。

2.        将数字证书导入jre可信任区。

keytool -import-alias castest -keypass changeit -keystore ../jre/lib/security/cacerts -filec:\castest.cer

3.        查看证书是否加入成功

keytool -list -aliascastest -keypass changeit -keystore ../jre/lib/security/cacerts

 

 

部署CASClient应用

CASClient的功能主要通过FilterListener的方式来实现,可以在客户端应用的web.xml中进行配置,主要有:

²  CAS Single Sign Out Filter

提供单点登出时需要的操作,配置如下:

 

<filter> 

              <filter-name>CAS  Single Sign Out Filter</filter-name>  

              <filter-class> 

                  org.jasig.cas.client.session.SingleSignOutFilter 

              </filter-class> 

</filter>

 

 

²  CAS Authentication Filter

提供提出认证时需要的操作,配置如下:

 

<filter>

                   <filter-name>CAS  Authentication Filter</filter-name>

                   <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>

                   <init-param>

                            <param-name>casServerLoginUrl</param-name>

                            <param-value>https://cas.testserver.com:8443/cas/login</param-value>

                   </init-param>

                   <init-param> 

                             

                            <param-name>serverName</param-name>

                            <param-value>http://192.168.184.1:8080</param-value>

                            <!-- 

                            <param-name>service</param-name>

                            <param-value>http://192.168.184.1:8080/cas-client2/index.jsp</param-value>

                            -->

                   </init-param>

         </filter>

 

 

 

²  CAS Validation Filter

提供校验票据有效性的相关功能,配置如下:

 

<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://cas.testserver.com:8443/cas</param-value>

                   </init-param>

                   <init-param>

                     

                            <param-name>serverName</param-name>

                            <param-value>http://192.168.184.1:8080</param-value>

                   <!--

                            <param-name>service</param-name>

                            <param-value>http://192.168.184.1:8080/cas-client2/index.jsp</param-value>

                   -->

                   </init-param>

         </filter>

 

 

 

²  CAS HttpServletRequest Wrapper Filter

包装request对象,以便通过request.getRemoteUser()的方法获取登录用户信息,配置如下:

 

<filter> 

                   <filter-name>CAS  HttpServletRequest Wrapper Filter</filter-name> 

                   <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>

</filter>

 

 

²  CAS Assertion Thread Local Filter

提供AssertionHolder的支持,可以通过AssertionHolder.getAssertion()方法获取登录信息,配置如下:

 

<filter> 

              <filter-name>CAS  Assertion Thread Local Filter</filter-name>  

             <filter-class>  

                  org.jasig.cas.client.util.AssertionThreadLocalFilter  

           </filter-class>  

</filter>  

 

 

²  SingleSignOutHttpSessionListener

提供单点登出时的事件监听,配置如下:

 

<listener> 

              <listener-class>  

                  org.jasig.cas.client.session.SingleSignOutHttpSessionListener  

         </listener-class>  

</listener>

 

 

 

CAS集群使用情况

CASClient集群情况

由于CASClient需要在Session中保存用户认证成功的信息,所以在集群环境下必须通过session同步或将认证信息统一存入memcache的方式来保证认证信息的一致性。

tomcat6.0自带的session同步机制为例,需要对所有节点的tomcat做以下配置:

1.        修改conf/server.xmlHost标签下,添加如下配置

 

                   <Cluster  className="org.apache.catalina.ha.tcp.SimpleTcpCluster">

 

           <Manager  className="org.apache.catalina.ha.session.DeltaManager"

                    expireSessionsOnShutdown="false"

                    notifyListenersOnReplication="true"/>

 

           <Channel className="org.apache.catalina.tribes.group.GroupChannel">

            <Membership

                 className="org.apache.catalina.tribes.membership.McastService"

                 address="239.255.0.1"

                port="45564"

                frequency="500"

                dropTime="3000"

                mcastTTL="1"/>

 

            <Receiver

                 className="org.apache.catalina.tribes.transport.nio.NioReceiver"

                 address="192.168.184.1"

                port="4000"

                autoBind="0"

                 selectorTimeout="100"

                maxThreads="6"/>

 

            <Sender  className="org.apache.catalina.tribes.transport.ReplicationTransmitter">

              <Transport  className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>

            </Sender>

            <Interceptor  className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>

            <Interceptor  className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>

 

           </Channel>

 

           <Valve  className="org.apache.catalina.ha.tcp.ReplicationValve"

                    filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;"/>

 

           <ClusterListener  className="org.apache.catalina.ha.session.ClusterSessionListener"/>

         </Cluster>

 

其中Membership Receiver中的 addressport需要根据实际情况调整

2.        确保web.xml中包含一下标签

 

<distributable/>

 

 

CASServer集群情况

CASServer本身会对相关票据信息进行存储,CAS提供多种票据存储策略(TicketRegistry),包括:

l  Default

l  BerkleyDB

l  EhcacheTicketRegistry

l  JBOSS TreeCache

l  JDBCTicketRegistry

l  MemcacheTicketRegistry

l  JpaTicketRegistry

默认的存储策略将相关票据信息保存在hashmap中,无法在集群环境下进行共享,如果需要集群部署,可以采用MemcacheTicketRegistry将票据信息统一保存在Memcache中,也可以采用JDBCTicketRegistry将票据信息保存在数据库中,以实现票据信息的共享。以下以MemcacheTicketRegistry为例进行说明:

1.        修改CASServer应用WEB-INF/spring-configuration/ticketRegistry.xml

2.        注释原默认存储策略

 

<!--

<bean id="ticketRegistry"  class="org.jasig.cas.ticket.registry.DefaultTicketRegistry" />

-->

 

3.        添加新的策略配置

 

<bean  id="ticketRegistry"  class="org.jasig.cas.ticket.registry.MemCacheTicketRegistry">

        <constructor-arg  index="0">

            <list>

                <value>machine1:11211</value>

                <value>machine2:11211</value>

            </list>

        </constructor-arg>

        <constructor-arg  index="1" type="int" value="21600" />

        <constructor-arg  index="2" type="int" value="300" />

 </bean>

 

 

 

 

参考资料

https://wiki.jasig.org/display/CASC/Home

https://wiki.jasig.org/display/CASUM/Home