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,代碼結構基本是進行了翻天覆地的重構,另外獲取客戶端信息時,也是只有最新版本的