cas配置与自定义开发

来源:互联网 发布:opencv车流量统计算法 编辑:程序博客网 时间:2024/06/05 02:06

1. 下载 cas server 源码

https://github.com/Jasig/cas/releases

我下载的是 4.0.1。你也可以直接checkout


cas client : http://downloads.jasig.org/cas-clients/

版本是 3.3.3


2. 将下载的 cas-4.0.1.zip 解压, 在根目录 执行 

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. mvn package install -Dmaven.test.skip=true  

执行完成后,可将 cas-server-webapp\target\cas.war 部署到tomcat


3. 生成证书

参考: http://kai2008.iteye.com/blog/1134238

生成服务器端证书

keytool -genkey  -v  -alias  tomcat1 -dname "cn=localhost,ou=cas,o=cas,c=CN" -keyalg  RSA  -keystore d:/tomcat1.keystore -storepass 123456   -keypass 123456 -validity 3650

为客户端生成证书
keytool -genkey  -v   -alias myKey -keyalg   RSA  -storetype PKCS12   -keystore d:/my1.p12   -dname "cn=localhost,ou=cas,o=cas,c=CN"  -storepass 123456   -keypass 123456   -validity 3650

让服务器信任客户端证书
keytool -export -alias myKey   -keystore d:/my1.p12  -storetype PKCS12 -rfc  -file d:/my1.cer

客户端证书导入到服务器的证书库
keytool -import -v   -file d:/my1.cer  -keystore d:/tomcat1.keystore -storepass 123456


让客户端信任服务器证书

keytool -keystore d:/tomcat1.keystore -export -alias tomcat1 -file d:/tomcat1.cer


在浏览器中导入服务器和客户端证书。

双击 tomcat1.cer 即可导入服务器证书。按照提示安装证书,将证书填入到“受信任的根证书颁发机构”。

 

双击 my1.p12 即可导入服务器证书。按照提示安装证书,将证书填入到“个人”。


注意,cn要设置为服务器地址,如 localhost,方便调试,否则后面cas server 回调 cas client 会出错:

[plain] view plain copy
  1. java.security.cert.CertificateException: No name matching localhost found  

为客户端的JVM导入密钥

keytool -import -file d:/tomcat1.cer -alias tomcat1 -keystore "%java_home%\jre\lib\security\cacerts"


查看证书
[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. keytool -list -v -keystore "%java_home%\jre\lib\security\cacerts" -alias localhost    

修改 tomcat conf server.xml :

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <Connector SSLEnabled="true" clientauth="false" keystoreFile="conf/tomcat1.keystore" keystorePass="123456" maxThreads="150"  
  2.                      port="8443" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS" />  



4. 开发 cas server

第一种:下载 cas server 源码后,执行

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. mvn eclipse:eclipse  
导入eclipse,这时会报错:
[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. Plugin execution not covered by lifecycle configuration:xxx plugin  

解决方法:

在 cas-4.0.1\pom.xml 里的 build - pluginManagement  - plugins 节点加入:

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <plugin>  
  2.             <groupId>org.eclipse.m2e</groupId>  
  3.             <artifactId>lifecycle-mapping</artifactId>  
  4.             <version>1.0.0</version>  
  5.             <configuration>  
  6.                <lifecycleMappingMetadata>  
  7.                   <pluginExecutions>  
  8.                     <pluginExecution>  
  9.                       <pluginExecutionFilter>  
  10.                         <groupId>org.apache.maven.plugins</groupId>  
  11.                         <artifactId>maven-checkstyle-plugin</artifactId>  
  12.                         <versionRange>2.10</versionRange>  
  13.                         <goals>  
  14.                           <goal>checkstyle</goal>  
  15.                         </goals>  
  16.                       </pluginExecutionFilter>  
  17.                       <action>  
  18.                         <ignore />  
  19.                       </action>  
  20.                     </pluginExecution>  
  21.                     <pluginExecution>  
  22.                       <pluginExecutionFilter>  
  23.                         <groupId>com.mycila.maven-license-plugin</groupId>  
  24.                         <artifactId>maven-license-plugin</artifactId>  
  25.                         <versionRange>1.9.0</versionRange>  
  26.                         <goals>  
  27.                           <goal>check</goal>  
  28.                         </goals>  
  29.                       </pluginExecutionFilter>  
  30.                       <action>  
  31.                         <ignore />  
  32.                       </action>  
  33.                     </pluginExecution>  
  34.                     <pluginExecution>  
  35.                       <pluginExecutionFilter>  
  36.                         <groupId>org.codehaus.mojo</groupId>  
  37.                         <artifactId>aspectj-maven-plugin</artifactId>  
  38.                         <versionRange>1.4</versionRange>  
  39.                         <goals>  
  40.                           <goal>compile</goal>  
  41.                         </goals>  
  42.                       </pluginExecutionFilter>  
  43.                       <action>  
  44.                         <ignore />  
  45.                       </action>  
  46.                     </pluginExecution>  
  47.                   </pluginExecutions>  
  48.                 </lifecycleMappingMetadata>  
  49.             </configuration>  
  50.         </plugin>  


第二种方法:

参考: http://jasig.github.io/cas/4.0.x/installation/Maven-Overlay-Installation.html

下载maven 模板: https://github.com/UniconLabs/simple-cas4-overlay-template/archive/master.zip

导入eclipse,import - maven - existing maven projects,在pom.xml加入依赖,支持访问数据库验证密码:


[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <dependencies>  
  2.         <dependency>  
  3.             <groupId>org.jasig.cas</groupId>  
  4.             <artifactId>cas-server-webapp</artifactId>  
  5.             <version>${cas.version}</version>  
  6.             <type>war</type>  
  7.             <scope>runtime</scope>  
  8.         </dependency>  
  9.           
  10.         <dependency>  
  11.             <groupId>org.jasig.cas</groupId>  
  12.             <artifactId>cas-server-core</artifactId>  
  13.             <version>${cas.version}</version>  
  14.         </dependency>  
  15.         <dependency>  
  16.             <groupId>org.jasig.cas</groupId>  
  17.             <artifactId>cas-server-support-jdbc</artifactId>  
  18.             <version>${cas.version}</version>  
  19.         </dependency>  
  20.         <dependency>  
  21.             <groupId>mysql</groupId>  
  22.             <artifactId>mysql-connector-java</artifactId>  
  23.             <version>5.1.35</version>  
  24.         </dependency>  
  25.         <dependency>  
  26.             <groupId>c3p0</groupId>  
  27.             <artifactId>c3p0</artifactId>  
  28.             <version>${c3p0.version}</version>  
  29.         </dependency>  
  30.                 <dependency>  
  31.             <groupId>org.springframework</groupId>  
  32.             <artifactId>spring-core</artifactId>  
  33.             <version>${spring.version}</version>  
  34.             <scope>compile</scope>  
  35.         </dependency>  
  36.         <dependency>  
  37.           <groupId>javax.validation</groupId>  
  38.           <artifactId>validation-api</artifactId>  
  39.           <version>${javax.validation.version}</version>  
  40.           <scope>compile</scope>  
  41.         </dependency>  
  42.   
  43.     </dependencies>  
  44.   
  45.     <properties>  
  46.         <cas.version>4.0.1</cas.version>  
  47.         <maven.compiler.source>1.7</maven.compiler.source>  
  48.         <maven.compiler.target>1.7</maven.compiler.target>  
  49.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  50.           
  51.         <spring.version>3.2.6.RELEASE</spring.version>  
  52.         <javax.validation.version>1.0.0.GA</javax.validation.version>  
  53.         <c3p0.version>0.9.1.2</c3p0.version>  
  54.     </properties>  



修改 deployerConfigContext.xml :

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">  
  2.         <constructor-arg>  
  3.             <map>  
  4.                  
  5.                 <entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />  
  6.                 <!--<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" /> -->  
  7.                 <entry key-ref="dbAuthHandler" value-ref="primaryPrincipalResolver"/>  
  8.             </map>  
  9.         </constructor-arg>  
  10.   
  11.           
  12.         <property name="authenticationPolicy">  
  13.             <bean class="org.jasig.cas.authentication.AnyAuthenticationPolicy" />  
  14.         </property>  
  15. </bean>  

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <!--   
  2.     <bean id="primaryAuthenticationHandler"  
  3.           class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">  
  4.         <property name="users">  
  5.             <map>  
  6.                 <entry key="casuser" value="Mellon"/>  
  7.             </map>  
  8.         </property>  
  9.     </bean>  
  10.     -->  
  11.     <bean id="dataSource"  
  12.       class="com.mchange.v2.c3p0.ComboPooledDataSource"  
  13.      p:driverClass="com.mysql.jdbc.Driver" p:jdbcUrl="jdbc:mysql://localhost:3306/portal_230?useUnicode=true&characterEncoding=UTF8&noAccessToProcedureBodies=true&autoReconnect=true&zeroDateTimeBehavior=convertToNull"  
  14.       p:user="root"  
  15.       p:password="root" />  
  16.   
  17.     <!-- 密码加密方式-->  
  18.     <bean id="passwordEncoder"  
  19.       class="com.my.cas.authentication.handler.SelfPasswordEncoder"  
  20.       c:encodingAlgorithm="SHA1"  
  21.       p:characterEncoding="UTF-8" />  
  22.   
  23.     <bean id="dbAuthHandler"  
  24.       class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"  
  25.       p:dataSource-ref="dataSource"  
  26.       p:sql="select password from test_user where username=? "  
  27.       p:passwordEncoder-ref="passwordEncoder"  
  28.       />  


其中的

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. com.my.cas.authentication.handler.SelfPasswordEncoder  

为自定义的密码加密类,实现接口 

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. org.jasig.cas.authentication.handler.PasswordEncoder  


5. 客户端

引入依赖

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <dependency>    
  2.             <groupId>org.jasig.cas.client</groupId>    
  3.             <artifactId>cas-client-core</artifactId>    
  4.             <version>3.2.1</version>    
  5.         </dependency>  


在web.xml加入filter
[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <!-- ======================== 单点登录开始 ======================== -->    
  2.     <!-- 用于单点退出,该过滤器用于实现单点登出功能,可选配置 -->    
  3.     <listener>    
  4.         <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>    
  5.     </listener>    
  6.     
  7.     <!-- 该过滤器用于实现单点登出功能,可选配置。 -->    
  8.     <filter>    
  9.         <filter-name>CAS Single Sign Out Filter</filter-name>    
  10.         <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>    
  11.     </filter>    
  12.     <filter-mapping>    
  13.         <filter-name>CAS Single Sign Out Filter</filter-name>    
  14.         <url-pattern>/*</url-pattern>    
  15.     </filter-mapping>    
  16.     
  17.     <!-- 该过滤器负责用户的认证工作,必须启用它 -->    
  18.     <filter>    
  19.         <filter-name>CASFilter</filter-name>    
  20.         <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>    
  21.         <init-param>    
  22.             <param-name>casServerLoginUrl</param-name>    
  23.             <param-value>https://sso.cas.com:8443/cas/login</param-value>    
  24.             <!--这里的server是服务端的IP -->    
  25.         </init-param>    
  26.         <init-param>    
  27.             <param-name>serverName</param-name>    
  28.             <param-value>http://localhost:8080</param-value><span style="color:#FF0000;"> ①</span>    
  29.         </init-param>    
  30.     </filter>    
  31.     <filter-mapping>    
  32.         <filter-name>CASFilter</filter-name>    
  33.         <url-pattern>/*</url-pattern>    
  34.     </filter-mapping>    
  35.     
  36.     <!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->    
  37.     <filter>    
  38.         <filter-name>CAS Validation Filter</filter-name>    
  39.         <filter-class>    
  40.             org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>    
  41.         <init-param>    
  42.             <param-name>casServerUrlPrefix</param-name>    
  43.             <param-value>https://sso.cas.com:8443/cas</param-value>    
  44.         </init-param>    
  45.         <init-param>    
  46.             <param-name>serverName</param-name>    
  47.             <param-value>http://localhost:8080</param-value>  <span style="color:#FF0000;"></span>    
  48.         </init-param>    
  49.     </filter>    
  50.     <filter-mapping>    
  51.         <filter-name>CAS Validation Filter</filter-name>    
  52.         <url-pattern>/*</url-pattern>    
  53.     </filter-mapping>    
  54.     
  55.     <!-- 该过滤器负责实现HttpServletRequest请求的包裹, 比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。 -->    
  56.     <filter>    
  57.         <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>    
  58.         <filter-class>    
  59.             org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>    
  60.     </filter>    
  61.     <filter-mapping>    
  62.         <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>    
  63.         <url-pattern>/*</url-pattern>    
  64.     </filter-mapping>    
  65.     
  66.     <!-- 该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。 比如AssertionHolder.getAssertion().getPrincipal().getName()。 -->    
  67.     <filter>    
  68.         <filter-name>CAS Assertion Thread Local Filter</filter-name>    
  69.         <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>    
  70.     </filter>    
  71.     <filter-mapping>    
  72.         <filter-name>CAS Assertion Thread Local Filter</filter-name>    
  73.         <url-pattern>/*</url-pattern>    
  74.     </filter-mapping>    
  75.     
  76.     <!-- ======================== 单点登录结束 ======================== -->    

写一个controller测试
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @Controller  
  2. public class TestController {  
  3.     @RequestMapping("/test")  
  4.     public void test(HttpServletRequest request,  
  5.             HttpServletResponse response) throws IOException{  
  6.         String username = AssertionHolder.getAssertion().getPrincipal().getName();  
  7.   
  8.         response.getWriter().print("hello, " + username );  
  9.           
  10.     }  
  11. }  

通过 
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. AssertionHolder.getAssertion().getPrincipal().getName()  
 获取用户名

6. 登录成功后返回更多用户信息

cas4.0 没有了 UsernamePasswordCredentialsToPrincipalResolver,而是提供了 org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver,需要配置 attributeRepository 属性

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <bean id="primaryPrincipalResolver"  
  2.       class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >  
  3.     <property name="attributeRepository" ref="attributeRepository" />  
  4. </bean>  

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <bean id="attributeRepository"  class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao" >  
  2.         <constructor-arg index="0" ref="dataSource"/>  
  3.         <constructor-arg index="1" value="select * from test_user where {0}"/>  
  4.         <property name="queryAttributeMapping">  
  5.             <map>  
  6. <!--                 // 这里的key需写username,value对应数据库用户名字段 -->  
  7.                 <entry key="username" value="username"/>    
  8.             </map>  
  9.         </property>  
  10.         <property name="resultAttributeMapping">  
  11.             <map>  
  12.                 <entry key="id" value="id"/>  
  13.                 <entry key="password" value="password"/>  
  14.                 <entry key="mobile" value="mobile"/>  
  15.                 <entry key="email" value="email"/>  
  16.             </map>  
  17.         </property>  
  18.     </bean>  

然后将 RegexRegisteredService 的配置改为

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <bean class="org.jasig.cas.services.RegexRegisteredService">  
  2.             <property name="id" value="1" />  
  3.             <property name="name" value="HTTP and IMAP on example.com" />  
  4.             <property name="description" value="Allows HTTP(S) and IMAP(S) protocols on example.com" />  
  5.             <property name="serviceId" value="^(https?|imaps?)://.*" />  
  6.             <property name="evaluationOrder" value="0" />  
  7. <!--             <property name="attributeFilter"> -->  
  8. <!--               <bean class="org.jasig.cas.services.support.RegisteredServiceRegexAttributeFilter" c:regex="^\w{3}$" />  -->  
  9. <!--             </property> -->  
  10. <!--             // 客户端需要使用的对象的属性名称 -->  
  11.             <property name="allowedAttributes">   
  12.                                 <list>  
  13.                                         <value>id</value>  
  14.                                         <value>email</value>  
  15.                                         <value>mobile</value>  
  16.                                 </list>  
  17.             </property>  
  18.         </bean>  

最后,修改 WEB-INF\view\jsp\protocol\2.0\casServiceValidationSuccess.jsp,加入

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <c:if test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes) > 0}">  
  2.           <cas:attributes>  
  3.               <c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">  
  4.                   <cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>  
  5.               </c:forEach>  
  6.           </cas:attributes>  
  7.       </c:if>  

客户端改为

[java] view plain copy
  1. @Controller  
  2. public class TestController {  
  3.     @RequestMapping("/test")  
  4.     public void test(HttpServletRequest request,  
  5.             HttpServletResponse response) throws IOException{  
  6.         String username = AssertionHolder.getAssertion().getPrincipal().getName();  
  7.         AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();  
  8.         Map<String, Object> attributes = principal.getAttributes();  
  9.         String email= (String)attributes.get("email");  
  10.         response.getWriter().print("hello, " + username + " . email:" + email);  
  11.           
  12.     }  
  13. }  


搞定!


参考:

http://zxs19861202.iteye.com/blog/890965

http://blog.csdn.net/small_love/article/details/6664831

http://jasig.github.io/cas/4.0.x/installation/Maven-Overlay-Installation.html


0 0
原创粉丝点击