SSO单点登录之二:Yale CAS实现单点登录(服务器端)

耶鲁大学开发的CAS单点登录系统在SSO中应该说是比较有名的啦,既然也是开源的,我们为何不拿过来学习学习呢

很早之前的耶鲁的CAS开源包地址是在:http://www.yale.edu/tp/auth/ 

目前的CAS开源包都已经转移到新网址了,并且开源包里面的类名都没有以yelu开头了而是jasing

CAS客户端:http://downloads.jasig.org/cas-clients/ 

CAS服务器端:http://www.jasig.org/cas/download 

我下载的都是目前最新版的cas-server-3.4.5服务器端和cas-client-3.2.0客户端

 

 CAS服务器端基础应用

1)将cas-server-3.4.zip解压到一个目录,将cas-server-3.4.5\modules\cas-server-webapp-3.4.5.war拷贝到tomcat的webapp中去,并且改名为CasServer.war.启动tomcat

2)现在可以访问CAS应用了,当然要使用HTTPS加密协议访问,例如本问用到地址:https://javacrazyer.sso.com:8443/CasServer/login,现在打开了CAS服务器的页面输入admin/admin点击登录(CAS默认的验证规则只要用户名和密码相同就通过)


 

所以如果你看到下面的这张图片你就成功了  



 

CAS服务器端深入应用,与数据库配置登录

 

首先打开tomcat/webapp/cas/WEB-INF/deployerConfigContext.xml文件,配置的地方如下:

 1)找到第92行处,注释掉:SimpleTestUsernamePasswordAuthenticationHandler这个验证Handler,这个是比较简单的,只是判断用户名和密码相同即可通过,这个肯定不能在实际应用中使用,弃用!  

 2)注释掉92行后在下面添加下面的代码:

 

Java代码   收藏代码
  1. <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">  
  2.         <property name="dataSource" ref="dataSource" />  
  3.         <property name="sql" value="select password from t_admin_user where login_name=?" />  
  4.         <property name="passwordEncoder" ref="MD5PasswordEncoder"/>  
  5. </bean>  

在文件的末尾结束之前加上如下

 

Xml代码   收藏代码
  1. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  2.    <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>  
  3.    <property name="url"><value>jdbc:mysql:///wsriademo</value></property>  
  4.    <property name="username"><value>root</value></property>  
  5.    <property name="password"><value>root</value></property>  
  6. </bean>  
  7.   
  8. <bean id="MD5PasswordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">    
  9.         <constructor-arg index="0">  
  10.                 <value>MD5</value>  
  11.         </constructor-arg>  
  12. </bean>  
 

完整的deployerConfigContext.xml如下

 

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!--  
  3.     | deployerConfigContext.xml centralizes into one file some of the declarative configuration that  
  4.     | all CAS deployers will need to modify.  
  5.     |  
  6.     | This file declares some of the Spring-managed JavaBeans that make up a CAS deployment.    
  7.     | The beans declared in this file are instantiated at context initialization time by the Spring   
  8.     | ContextLoaderListener declared in web.xml.  It finds this file because this  
  9.     | file is among those declared in the context parameter "contextConfigLocation".  
  10.     |  
  11.     | By far the most common change you will need to make in this file is to change the last bean  
  12.     | declaration to replace the default SimpleTestUsernamePasswordAuthenticationHandler with  
  13.     | one implementing your approach for authenticating usernames and passwords.  
  14.     +-->  
  15. <beans xmlns="http://www.springframework.org/schema/beans"  
  16.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  17.        xmlns:p="http://www.springframework.org/schema/p"  
  18.        xmlns:sec="http://www.springframework.org/schema/security"  
  19.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  20.        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">  
  21.     <!--  
  22.         | This bean declares our AuthenticationManager.  The CentralAuthenticationService service bean  
  23.         | declared in applicationContext.xml picks up this AuthenticationManager by reference to its id,   
  24.         | "authenticationManager".  Most deployers will be able to use the default AuthenticationManager  
  25.         | implementation and so do not need to change the class of this bean.  We include the whole  
  26.         | AuthenticationManager here in the userConfigContext.xml so that you can see the things you will  
  27.         | need to change in context.  
  28.         +-->  
  29.     <bean id="authenticationManager"  
  30.         class="org.jasig.cas.authentication.AuthenticationManagerImpl">  
  31.         <!--  
  32.             | This is the List of CredentialToPrincipalResolvers that identify what Principal is trying to authenticate.  
  33.             | The AuthenticationManagerImpl considers them in order, finding a CredentialToPrincipalResolver which   
  34.             | supports the presented credentials.  
  35.             |  
  36.             | AuthenticationManagerImpl uses these resolvers for two purposes.  First, it uses them to identify the Principal  
  37.             | attempting to authenticate to CAS /login .  In the default configuration, it is the DefaultCredentialsToPrincipalResolver  
  38.             | that fills this role.  If you are using some other kind of credentials than UsernamePasswordCredentials, you will need to replace  
  39.             | DefaultCredentialsToPrincipalResolver with a CredentialsToPrincipalResolver that supports the credentials you are  
  40.             | using.  
  41.             |  
  42.             | Second, AuthenticationManagerImpl uses these resolvers to identify a service requesting a proxy granting ticket.   
  43.             | In the default configuration, it is the HttpBasedServiceCredentialsToPrincipalResolver that serves this purpose.   
  44.             | You will need to change this list if you are identifying services by something more or other than their callback URL.  
  45.             +-->  
  46.         <property name="credentialsToPrincipalResolvers">  
  47.             <list>  
  48.                 <!--  
  49.                     | UsernamePasswordCredentialsToPrincipalResolver supports the UsernamePasswordCredentials that we use for /login   
  50.                     | by default and produces SimplePrincipal instances conveying the username from the credentials.  
  51.                     |   
  52.                     | If you've changed your LoginFormAction to use credentials other than UsernamePasswordCredentials then you will also  
  53.                     | need to change this bean declaration (or add additional declarations) to declare a CredentialsToPrincipalResolver that supports the  
  54.                     | Credentials you are using.  
  55.                     +-->  
  56.                 <bean  
  57.                     class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" />  
  58.                 <!--  
  59.                     | HttpBasedServiceCredentialsToPrincipalResolver supports HttpBasedCredentials.  It supports the CAS 2.0 approach of  
  60.                     | authenticating services by SSL callback, extracting the callback URL from the Credentials and representing it as a  
  61.                     | SimpleService identified by that callback URL.  
  62.                     |  
  63.                     | If you are representing services by something more or other than an HTTPS URL whereat they are able to  
  64.                     | receive a proxy callback, you will need to change this bean declaration (or add additional declarations).  
  65.                     +-->  
  66.                 <bean  
  67.                     class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />  
  68.             </list>  
  69.         </property>  
  70.   
  71.         <!--  
  72.             | Whereas CredentialsToPrincipalResolvers identify who it is some Credentials might authenticate,   
  73.             | AuthenticationHandlers actually authenticate credentials.  Here we declare the AuthenticationHandlers that  
  74.             | authenticate the Principals that the CredentialsToPrincipalResolvers identified.  CAS will try these handlers in turn  
  75.             | until it finds one that both supports the Credentials presented and succeeds in authenticating.  
  76.             +-->  
  77.         <property name="authenticationHandlers">  
  78.             <list>  
  79.                 <!--  
  80.                     | This is the authentication handler that authenticates services by means of callback via SSL, thereby validating  
  81.                     | a server side SSL certificate.  
  82.                     +-->  
  83.                 <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"  
  84.                     p:httpClient-ref="httpClient" />  
  85.                 <!--  
  86.                     | This is the authentication handler declaration that every CAS deployer will need to change before deploying CAS   
  87.                     | into production.  The default SimpleTestUsernamePasswordAuthenticationHandler authenticates UsernamePasswordCredentials  
  88.                     | where the username equals the password.  You will need to replace this with an AuthenticationHandler that implements your  
  89.                     | local authentication strategy.  You might accomplish this by coding a new such handler and declaring  
  90.                     | edu.someschool.its.cas.MySpecialHandler here, or you might use one of the handlers provided in the adaptors modules.  
  91.                     +-->  
  92.                 <!--<bean  
  93.                     class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />  
  94.             -->  
  95.     <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">  
  96.         <property name="dataSource" ref="dataSource" />  
  97.         <property name="sql" value="select password from t_admin_user where login_name=?" />  
  98.         <property name="passwordEncoder" ref="myPasswordEncoder"/>  
  99.     </bean>  
  100.             </list>  
  101.         </property>  
  102.     </bean>  
  103.   
  104.   
  105.     <!--  
  106.     This bean defines the security roles for the Services Management application.  Simple deployments can use the in-memory version.  
  107.     More robust deployments will want to use another option, such as the Jdbc version.  
  108.       
  109.     The name of this should remain "userDetailsService" in order for Spring Security to find it.  
  110.      -->  
  111.     <!-- <sec:user name="@@THIS SHOULD BE REPLACED@@" password="notused" authorities="ROLE_ADMIN" />-->  
  112.   
  113.     <sec:user-service id="userDetailsService">  
  114.         <sec:user name="@@THIS SHOULD BE REPLACED@@" password="notused" authorities="ROLE_ADMIN" />  
  115.     </sec:user-service>  
  116.       
  117.     <!--   
  118.     Bean that defines the attributes that a service may return.  This example uses the Stub/Mock version.  A real implementation  
  119.     may go against a database or LDAP server.  The id should remain "attributeRepository" though.  
  120.      -->  
  121.     <bean id="attributeRepository"  
  122.         class="org.jasig.services.persondir.support.StubPersonAttributeDao">  
  123.         <property name="backingMap">  
  124.             <map>  
  125.                 <entry key="uid" value="uid" />  
  126.                 <entry key="eduPersonAffiliation" value="eduPersonAffiliation" />   
  127.                 <entry key="groupMembership" value="groupMembership" />  
  128.             </map>  
  129.         </property>  
  130.     </bean>  
  131.       
  132.     <!--   
  133.     Sample, in-memory data store for the ServiceRegistry. A real implementation  
  134.     would probably want to replace this with the JPA-backed ServiceRegistry DAO  
  135.     The name of this bean should remain "serviceRegistryDao".  
  136.      -->  
  137.     <bean  
  138.         id="serviceRegistryDao"  
  139.         class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl">  
  140.             <property name="registeredServices">  
  141.                 <list>  
  142.                     <bean class="org.jasig.cas.services.RegisteredServiceImpl">  
  143.                         <property name="id" value="0" />  
  144.                         <property name="name" value="HTTP" />  
  145.                         <property name="description" value="Only Allows HTTP Urls" />  
  146.                         <property name="serviceId" value="http://**" />  
  147.                     </bean>  
  148.   
  149.                     <bean class="org.jasig.cas.services.RegisteredServiceImpl">  
  150.                         <property name="id" value="1" />  
  151.                         <property name="name" value="HTTPS" />  
  152.                         <property name="description" value="Only Allows HTTPS Urls" />  
  153.                         <property name="serviceId" value="https://**" />  
  154.                     </bean>  
  155.   
  156.                     <bean class="org.jasig.cas.services.RegisteredServiceImpl">  
  157.                         <property name="id" value="2" />  
  158.                         <property name="name" value="IMAPS" />  
  159.                         <property name="description" value="Only Allows HTTPS Urls" />  
  160.                         <property name="serviceId" value="imaps://**" />  
  161.                     </bean>  
  162.   
  163.                     <bean class="org.jasig.cas.services.RegisteredServiceImpl">  
  164.                         <property name="id" value="3" />  
  165.                         <property name="name" value="IMAP" />  
  166.                         <property name="description" value="Only Allows IMAP Urls" />  
  167.                         <property name="serviceId" value="imap://**" />  
  168.                     </bean>  
  169.                 </list>  
  170.             </property>  
  171.         </bean>  
  172.           
  173. <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">  
  174.    <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>  
  175.    <property name="url"><value>jdbc:mysql:///javacrazyer</value></property>  
  176.    <property name="username"><value>root</value></property>  
  177.    <property name="password"><value>root</value></property>  
  178. </bean>  
  179. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  180.    <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>  
  181.    <property name="url"><value>jdbc:mysql:///javacrazyer</value></property>  
  182.    <property name="username"><value>root</value></property>  
  183.    <property name="password"><value>root</value></property>  
  184. </bean>  
  185.   
  186. <bean id="myPasswordEncoder" class="org.jasig.cas.authentication.handler.MyPasswordEncoder"/>  
  187. <bean id="MD5PasswordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">    
  188.         <constructor-arg index="0">  
  189.                 <value>MD5</value>  
  190.         </constructor-arg>  
  191. </bean>  
  192.   
  193. </beans>  

2.1)dataSource,就是使用JDBC查询时的数据源

这里呢关于dataSource的配置可以采用多种方式,正如我的配置文件中采用了spring支持的dataSource(这里需要添加cas-server-3.4.5\modules\cas-server-support-jdbc-3.4.5.jar),也采用了dbcp的方式(这里需要添加commons-dbcp.jar和commons-pool.jar),当然少不了添加MySQL驱动包了,当然我们可以配置N多种数据源在这里,真用到的其实只会有一个, <property name="dataSource" ref="dataSource" />这句话可以引用你想要的数据源。

这里关于数据源配置可以参考我早前写的关于spring数据源配置方式的文章

2.2)passwordEncoder:处理密码加密

细心的朋友从最后面的代码可以看到MD5加密的类有两个实MD5PasswordEncoder就是默认我们只需把摸认类添

加上无需写其他继承类,而如果你非要继承的话,那么就写你自己的类继承自PasswordEncoder,具体可以更改encode方法

我这里就选择使用了继承的方式,我写的类如下

 

Java代码   收藏代码
  1. package org.jasig.cas.authentication.handler;  
  2.   
  3. import java.security.MessageDigest;  
  4. import java.security.NoSuchAlgorithmException;  
  5.   
  6. public final class MyPasswordEncoder implements PasswordEncoder {  
  7.   
  8.     public MyPasswordEncoder() {  
  9.     };  
  10.   
  11.     public String encode(String password) {  
  12.         if (password == null || password.length() == 0) {  
  13.             throw new IllegalArgumentException(  
  14.                     "String to encript cannot be null or zero length");  
  15.         }  
  16.   
  17.         StringBuffer hexString = new StringBuffer();  
  18.   
  19.         try {  
  20.             MessageDigest md = MessageDigest.getInstance("MD5");  
  21.             md.update(password.getBytes());  
  22.             byte[] hash = md.digest();  
  23.   
  24.             for (int i = 0; i < hash.length; i++) {  
  25.                 if ((0xff & hash[i]) < 0x10) {  
  26.                     hexString.append("0"  
  27.                             + Integer.toHexString((0xFF & hash[i])));  
  28.                 } else {  
  29.                     hexString.append(Integer.toHexString(0xFF & hash[i]));  
  30.                 }  
  31.             }  
  32.         } catch (NoSuchAlgorithmException e) {  
  33.             e.printStackTrace();  
  34.         }  
  35.   
  36.         return hexString.toString();  
  37.     }  
  38.   
  39. }  

 当然你也可以选择不继承,采用默认的,都由 <property name="passwordEncoder" ref="MD5PasswordEncoder"/>来决定选择哪个加密方式。

 

2.3)QueryDatabaseAuthenticationHandler是cas-server-support-jdbc提供的查询接口其中一个,QueryDatabaseAuthenticationHandler是通过配置一个 SQL 语句查出密码,与所给密码匹配 

 

2.4)sql:登录查询哪一张表

这里大家或许还有一句话可以看到<property name="sql" value="select password from t_admin_user where login_name=?" />

所以需要用到数据库脚本,数据库名称我这里起名为javacrazyer

Sql代码   收藏代码
  1. /*  
  2. Navicat MySQL Data Transfer  
  3. Source Host     : localhost:3306  
  4. Source Database : javacrazyer  
  5. Target Host     : localhost:3306  
  6. Target Database : javacrazyer  
  7. Date: 2011-01-21 15:19:40  
  8. */  
  9.   
  10. SET FOREIGN_KEY_CHECKS=0;  
  11. -- ----------------------------  
  12. -- Table structure for area_info  
  13. -- ----------------------------  
  14. DROP TABLE IF EXISTS `area_info`;  
  15. CREATE TABLE `area_info` (  
  16.   `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '地区ID',  
  17.   `area_code` varchar(32) NOT NULL COMMENT '地区编码',  
  18.   `area_name` varchar(60) NOT NULL COMMENT '地区名称',  
  19.   `parent_area_id` bigint(20) NOT NULL COMMENT '上级ID',  
  20.   `area_number` char(6) DEFAULT NULL,  
  21.   `country_code` varchar(32) DEFAULT NULL,  
  22.   `area_level` int(11) NOT NULL,  
  23.   `enabled` bit(1) NOT NULL,  
  24.   `sort` int(11) DEFAULT NULL,  
  25.   `remark` varchar(255) DEFAULT NULL,  
  26.   PRIMARY KEY (`id`),  
  27.   KEY `bmc_bd_uqareainfo` (`area_code`)  
  28. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;  
  29.   
  30. -- ----------------------------  
  31. -- Records of area_info  
  32. -- ----------------------------  
  33.   
  34. -- ----------------------------  
  35. -- Table structure for city  
  36. -- ----------------------------  
  37. DROP TABLE IF EXISTS `city`;  
  38. CREATE TABLE `city` (  
  39.   `ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '城市ID',  
  40.   `CITY_NAME` varchar(20) NOT NULL COMMENT '城市名称',  
  41.   `SUPER_ID` bigint(20) NOT NULL COMMENT '上级城市(没有为-1)',  
  42.   `REMARK` varchar(255) DEFAULT NULL COMMENT '城市备注',  
  43.   PRIMARY KEY (`ID`)  
  44. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='城市';  
  45.   
  46. -- ----------------------------  
  47. -- Records of city  
  48. -- ----------------------------  
  49.   
  50. -- ----------------------------  
  51. -- Table structure for t_admin_user  
  52. -- ----------------------------  
  53. DROP TABLE IF EXISTS `t_admin_user`;  
  54. CREATE TABLE `t_admin_user` (  
  55.   `id` int(11) NOT NULL AUTO_INCREMENT,  
  56.   `passwordvarchar(255) DEFAULT NULL,  
  57.   `email` varchar(255) DEFAULT NULL,  
  58.   `namevarchar(255) DEFAULT NULL,  
  59.   `login_name` varchar(255) DEFAULT NULL,  
  60.   PRIMARY KEY (`id`)  
  61. ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;  
  62.   
  63. -- ----------------------------  
  64. -- Records of t_admin_user  
  65. -- ----------------------------  
  66. INSERT INTO `t_admin_user` VALUES ('1''88f6f4ddbd7160aa6a547589af036ee0'nullnull'cheneywu');  
  67. INSERT INTO `t_admin_user` VALUES ('2''098f6bcd4621d373cade4e832627b4f6'nullnull'test');  
 

 到这里你就认为完事了?看到我脚本中的密码的值是MD5加密过的,为什么加密?2.2中已经介绍过了,所以对于用户名/密码为:test/test的账户来说,在数据库中就应该为test/8f6bcd4621d373cade4e832627b4f6.这个密码值是怎么得到的,sql语言

中可以进行操作:select md5("test")

给力上图


这时你再去访问地址:https://javacrazyer.sso.com:8443/CasServer/login,输入数据库中存在的相同值的用户名密码,就能成功登陆了

 

关于CAS客户端SSO登录下一篇文章将会介绍

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值