yale cas 3.4如何返回更多信息高级篇
序:
Yale cas是目前项目中用到最多的SSO整合方案,cas的原理在很多文章中都有所说明,这里就不再多进行叙述了,从实战出发,结合实际项目整合的经验是非常值得借鉴的,了解cas的同志们都知道,在cas提供的demo中,返回给客户端的用户信息很少,只有一个登录用户名,而在实际应用中,客户端需要知道更多的用户信息,比如用户的性别,年龄,爱好,地址,用户的分组,角色信息等等,那么,下面就给大家介绍cas server
一、首先需要配置属性仓库attributeRepository,顾名思义,只用来存储相关的属性信息的,在领域分析模型中,就介绍了关于领域对象的资源库的概念,主要目的也是为了与客户程序解耦。首先,你需要到WEB-INF目录找到deployerConfigContext.xml文件,同时配置attributeRepository如下:
<bean class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao" id="attributeRepository"> <constructor-arg index="0" ref="casDataSource"/> <constructor-arg index="1" value="select * from sec_user where {0}"/> <property name="queryAttributeMapping"> <map> <entry key="username" value="user_iidd"/> </map> </property> <property name="resultAttributeMapping"> <map> <entry key="user_iidd" value="username"/> <entry key="user_name" value="user_name"/> <entry key="user_sex" value="user_sex"/> </map> </property> </bean> |
这里将进行说明一下,SingleRowJdbcPersonAttributeDao的构造函数需要提供两个参数,数据源DataSource和查询用户信息的sql。
public SingleRowJdbcPersonAttributeDao(DataSource ds, String sql) { super(ds, sql); } |
构造函数配置完成后,需要配置queryAttributeMapping和resultAttributeMapping,查询官方网站说明如下:
Property | Type | Default Value | |
queryAttributeMapping | Map<String, ?> | null | A Map from attribute names used in the Map to attribute names to use in the SQL. The values can be either String or Collection<String> to use a single Map attribute under multiple names as in the SQL. If set only Map attributes listed will be used in the SQL. If not set all Map attributes are used as-is in the SQL. |
resultAttributeMapping | Map<String, ?> | null | A Map from SQL result names to returned attribute names. The values can be either String or Collection<String> to use a single SQL result under multiple returned attributes. If set only SQL attributes listed will be returned. If not set all SQL attributes will be returned. |
其中queryAttributeMapping是组装sql用的查询条件属性,如下表中
二、配置用户认证凭据转化的解析器,也是在deployerConfigContext.xml中,找到
credentialsToPrincipalResolvers,为UsernamePasswordCredentialsToPrincipalResolver注入attributeRepository,那么attributeRepository就会被触发并通过此类进行解析,红色为新添部分。
<property name="credentialsToPrincipalResolvers"> <list> <bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver"> <property name="attributeRepository" ref="attributeRepository"/> </bean> <bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver"/> </list> </property> |
三、修改WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp,在server验证成功后,这个页面负责生成与客户端交互的xml信息,信息格式如下:
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'> <cas:authenticationSuccess> <cas:user>admin</cas:user> <cas:attributes> <cas:attribute> <cas:name>userId</cas:name> <cas:value>admin</cas:value> </cas:attribute> <cas:attribute> <cas:name>userSex</cas:name> <cas:value>M</cas:value> </cas:attribute> <cas:attribute> <cas:name>userName</cas:name> <cas:value>系统管理员</cas:value> </cas:attribute> </cas:attributes> </cas:authenticationSuccess> </cas:serviceResponse> |
在默认的casServiceValidationSuccess.jsp中,只包括用户名
<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:attribute> <cas:name>${fn:escapeXml(attr.key)}</cas:name> <cas:value>${fn:escapeXml(attr.value)}</cas:value> </cas:attribute> </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> |
通过完成上面三个步骤的配置后,server端的工作就完成了,那么如何在客户端获取这些信息呢?下面进行说明:
获取远程用户 request.getRemoteUser() 获取其他信息 AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal(); Map attributes = principal.getAttributes(); |
备注:总体来说,cas的代码结构不是很完善,尤其是客户端,从2.x到3.x,代码结构基本是进行了翻天覆地的重构,另外获取客户端信息时,也是只有最新版本的