CAS服務端返回更多的使用者登入資訊
從cas server登入成功後,預設只能從cas server得到使用者名稱。但程式中也可能遇到需要得到更多如姓名,手機號,email等更多使用者資訊的情況。cas client拿到使用者名稱後再到資料庫中查詢,的確可以得到關於該使用者的更多資訊。但是如果使用者登入成功後,直接從cas server返回給cas client使用者的詳細資訊,這也是一個不錯的做法。這個好處,尤其是在分散式中得以彰顯,cas server可以把使用者資訊傳遞給各個應用系統,如果是上面那種做法,那麼各個系統得到使用者名稱後,都得去資料庫中查詢一遍,無疑是一件重複性工作。
1、首先需要配置屬性attributeRepository
WEB-INF目錄找到 deployerConfigContext.xml檔案,同時配置 attributeRepository如下:
<beanclass="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao"id="attributeRepository">
<constructor-argindex="0"ref="dataSource"/>
<constructor-argindex="1"value="select * from t_user where {0}"
<propertyname="queryAttributeMapping">
<map>
<!--這裡的key需寫username和登入頁面一致,value對應資料庫使用者名稱欄位-->
<entrykey="username"value="loginname"/>
</map>
</property>
<propertyname="resultAttributeMapping">
<map>
<!--key為對應的資料庫欄位名稱,value為提供給客戶端獲取的屬性名字,系統會自動填充值-->
<entrykey="suid"value="suid"/>
</map>
</property>
<!--
<property name="queryType">
<value>OR</value>
</property>
-->
</bean>
切記:查詢出來的欄位名中間不能使用 _ (下劃線),否則獲取不到資料,如 cell_phone需要設定別名為
cellPhone.queryAttributeMapping是組裝sql用的查詢條件屬性,上述配置後,結合封裝成查詢sql就是
select* from userinfo where loginname=#username#resultAttributeMapping是sql執行完畢後返回的結構屬性, key對應資料庫欄位,value對應客戶端獲取引數。如果要組裝多個查詢條件,需要加上下面這個,預設為AND.
<propertyname="queryType">
<value>OR</value>
</property>
2、修改serviceRegistryDao
deployerConfigContext.xml中的 beans中id為serviceRegistryDao的屬性 registeredServicesList。在 registeredServicesList中新增allowedAttributes屬性的值。列出的每個值,在客戶端就可以訪問了。
<util:listid="registeredServicesList">
<beanclass="org.jasig.cas.services.RegexRegisteredService"
p:id="0"p:name="HTTP andIMAP"p:description="Allows HTTP(S) and IMAP(S) protocols"
p:serviceId="^(http?|https?|imaps?)://.*"p:evaluationOrder="10000001">
<!--新增該屬性allowedAttributes -->
<propertyname="allowedAttributes">
<list>
<value>suid</value>
</list>
</property>
<!-- ignoreAttributes為true表示配置的 resultAttributeMapping 會返回-->
<propertyname="ignoreAttributes" value="true" />
</bean>
此步驟非常重要,可以看看org.jasig.cas.services.RegexRegisteredService的原始碼,其中的allowedAttributes是關鍵。
如果獲取不到屬性,則需要新增如下屬性值:
<!-- ignoreAttributes為true表示配置的 resultAttributeMapping會返回-->
<propertyname="ignoreAttributes" value="true" />
3、修改casServiceValidationSuccess.jsp
WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp.在server驗證成功後,這個頁面負責生成與客戶端互動的xml資訊,在預設的casServiceValidationSuccess.jsp中,只包括使用者名稱,並不提供其他的屬性資訊,因此需要對頁面進行擴充套件。如下:
<cas:serviceResponsexmlns: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:iftest="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes)> 0}">
<cas:attributes>
<c:forEachvar="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:iftest="${notempty pgtIou}">
<cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
</c:if>
<c:iftest="${fn:length(assertion.chainedAuthentications)> 1}">
<cas:proxies>
<c:forEachvar="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>
4、CAS Client獲取使用者資訊
AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();
Map attributes = principal.getAttributes();
String email = attributes.get(“suid”);