cas单点登录反回用户多字段数据笔记

准备工作

下载cas客户端与服务器端包,这里介绍的版本为

client : 3.2.1

server : 3.5.2

cas部署

       CAS Server 是一套基于 Java 实现的服务,该服务以一个 Java Web Application 单独部署在与 servlet2.3 兼容的 Web 服务器上,另外,如果 Client 与 CAS Server 之间的交互采用 Https 协议通信的话,部署 CAS Server 的服务器还需要支持 SSL 协议。当 SSL 配置成功过后,像普通 Web 应用一样将 CAS Server 部署在服务器上就能正常运行了。

证书生成

1,我们用java的keytool工具生成store文件, 命令如下,按提示操作输入相关信息

keytool -genkey -keystore d:/tomcat.store -alias tomcat

2,生成cert文件

keytool -export -file D:/tomcat.cert -alias tomcat -keystore d:/tomcat.store

3,导入我们jdk

keytool -import -keystore D:\Java\jdk1.6.0_31\jre\lib\security\cacerts -file d:/tomcat.cert -alias tomcat

tomcat server.xml文件中打开https支持

在tomcat的config server.xml中打开 Connector结点

<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true" 
             maxThreads="150" scheme="https" secure="true"   
             keystoreFile="yourPath/xx.keystore" keystorePass="yourPwd"  
             clientAuth="false" sslProtocol="TLS" />  

 这里注意下,在tomcat6某些版本下

 protocol="HTTP/1.1 "      

 改为 

 protocol="org.apache.coyote.http11.Http11Protocol"  

否则起动会报错

cas server客户端配制

       这里通过mysql数据库认证,所以事先加入mysql的依赖包和cas 对jdbc支持的jar包

配制deployerConfigContext.xml

1,我们配制一个数据源:

<!-- 配制数据源 -->
<bean id="casDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/xxx</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>xxx</value>
</property>
</bean>

2,密码一般都采用md5或是其它算法加密,所以还要配制一个加密器(这里用内置的当然你也可以自定义)

<!-- 加密器 -->
<bean id="MD5PasswordEncoder"
class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">
<constructor-arg index="0">
<value>MD5</value>
</constructor-arg>
</bean>

 

3,AuthenticationHandler

【http://www.ibm.com/developerworks/cn/opensource/os-cn-cas/ 文章中的原话】

        在 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,在文件中可以找到如下一行:<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePassword

AuthenticationHandler" />,我们可以将其注释掉,换成我们希望的一个 AuthenticationHandler,比如,使用QueryDatabaseAuthenticationHandler 或 SearchModeSearchDatabaseAuthenticationHandler

我们这里配制为:

<!-- 注释掉简单的登录验证 替换成下面bean
<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler"
/> -->

<bean
class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="casDataSource" />
<property name="sql"
value="select PASSWORD from xxx where lower(LOGINNAME) = lower(?)" />
   <property name="passwordEncoder" ref="MD5PasswordEncoder" /> 
</bean>

  4,这里是反回用户的更多信息,所以还需要配制如下信息

 <!-- 反回数据字段 -->
<bean class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao"
id="attributeRepository">
 <constructor-arg index="0" ref="casDataSource" />
 <constructor-arg index="1" value="select * from xxx where {0}" />
 <property name="queryAttributeMapping">
     <map>
         <!-- 这里的key需写username,value对应数据库用户名字段 -->
         <entry key="username" value="LOGINNAME" />
     </map>
 </property>
<!-- sql执行完毕后返回的结构属性, key对应数据库字段,value对应客户端获取参数 -->
 <property name="resultAttributeMapping">
     <map>
         <entry key="USERID" value="id" />
         <entry key="LOGINNAME" value="loginName" />
         <entry key="USERNAME" value="name" />
     </map>
 </property>
</bean>

注: 这里反回*时,对于日期字段为'0000-00-00'这样的格式会报错,所以数据库数据要规范下,或是不用*反回所有而是直接写你需要的字段

5,这里还没完,对于反回多字段信息在需要如下配制

<bean class="org.jasig.cas.services.RegexRegisteredService">
<property name="id" value="0" />
<property name="name" value="HTTP and IMAP" />
<property name="description" value="Allows HTTP(S) and IMAP(S) protocols" />
<property name="serviceId" value="^(https?|imaps?)://.*" />
<property name="evaluationOrder" value="10000001" />
<!-- 3.5返回自定义数据字段新添加属性-->
<property name="ignoreAttributes" value="true" /> 
<!-- 3.4属性
<property name="allowedAttributes">
<list>
<value>....</value>
</list>
</property>
-->
</bean>

jsp页面的扩展

     

      因为反回多个字段,所以还要对反回数据的WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp页面做扩展

1,页面顶部加入<%@page pageEncoding="UTF-8"%>(对中文处理)

2,对生成数据交互的xml做扩展

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>${fn:escapeXml(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.id)}</cas:user>
 <!-- 扩展部份开始 -->
 <c:if test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes) > 0}">
            <cas:attributes>
                <c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
                    <cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>
                </c:forEach>
            </cas:attributes>
        </c:if>
<!-- 扩展部份结束 -->
<c:if test="${not empty pgtIou}">
<cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
</c:if>
<c:if test="${fn:length(assertion.chainedAuthentications) > 1}">
<cas:proxies>
<c:forEach var="proxy" items="${assertion.chainedAuthentications}"
varStatus="loopStatus" begin="0"
end="${fn:length(assertion.chainedAuthentications)-2}" step="1">
<cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy>
</c:forEach>
</cas:proxies>
</c:if>
</cas:authenticationSuccess>
</cas:serviceResponse>

登录中文乱码解决

     好了现在服务器端配制基本结束,但对于登录过程带中文乱码的还末解决,这时在服务器端的web.xml中配制个过滤器

<!-- 防提交参数中文乱码 -->
<filter> 
<filter-name>encodingFilter</filter-name> 
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
     <init-param> 
          <param-name>encoding</param-name> 
          <param-value>utf-8</param-value> 
     </init-param> 
</filter> 

<filter-mapping> 
    <filter-name>encodingFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
</filter-mapping> 

  

  

  客户端配制:

  

  这里直接贴配制

  

<!-- 用于单点退出,该过滤器用于实现单点登出功能 -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</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>
<!--认证服务端url -->
<param-name>casServerLoginUrl</param-name>
<param-value>https://localhost:8443/cas/login</param-value>
</init-param>
<init-param>
<!-- 客户端url -->
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 该过滤器负责对Ticket的校验工作,必须启用 -->
<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://localhost:8443/cas/</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
<!-- 防获取参数中文乱码 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 该过滤器负责实现HttpServletRequest请求的包裹,比如允许开发者 通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。 -->
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder 来获取用户的登录名, 比如AssertionHolder.getAssertion().getPrincipal().getName()。 -->
<filter>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 自动根据单点登录的结果设置本系统的用户信息,AutoSetUserAdapterFilter就是一个自定义过过滤器,它主要做一些用户数据的本系统的处理工作(如用户信息session的放入) -->
<filter>
<display-name>AutoSetUserAdapterFilter</display-name>
<filter-name>AutoSetUserAdapterFilter</filter-name>
<filter-class> com.common.filter.AutoSetUserAdapterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AutoSetUserAdapterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

  

  客户端获取用户信息:

AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
Map<String, Object> user = principal.getAttributes();

  这里的user的map中就是你反回的用户信息字段数据

猜你喜欢

转载自fhqibjg.iteye.com/blog/1922870