基於CAS實現單點登錄(SSO):登錄成功後,cas client如何返回更多用戶信息

cas server登錄成功後,默認只能從casclient得到用戶名。但程序中也可能遇到需要得到更多如姓名,手機號,email等更多用戶信息的情況。

cas client拿到用戶名後再到數據庫中查詢,的確可以得到關於該用戶的更多信息。

但是如果用戶登錄成功後,直接從cas server返回給casclient用戶的詳細信息,這也是一個不錯的做法。這個好處,尤其是在分佈式中得以彰顯,cas server可以把用戶信息傳遞給各個應用系統,如果是上面那種做法,那麼各個系統得到用戶名後,都得去數據庫中查詢一遍,無疑是一件重複性工作。

 

文章中 CAS 基礎環境:

cas-server-3.5.2    

cas-client-3.2.1

 一、首先需要配置屬性attributeRepository

首先,你需要到WEB-INF目錄找到 deployerConfigContext.xml文件,同時配置attributeRepository 如下: 

<bean  class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao"id="attributeRepository">
        <constructor-argindex="0" ref="casDataSource"/>
        <constructor-argindex="1" value="select * from userinfo where {0}"/>
        <propertyname="queryAttributeMapping">
            <map>
                <entrykey="username" value="loginname"/>  // 這裏的key需寫username和登錄頁面一致,value對應數據庫用戶名字段
            </map>
        </property>
        <propertyname="resultAttributeMapping">
            <map>
// <!--key爲對應的數據庫字段名稱,value爲提供給客戶端獲取的屬性名字,系統會自動填充值-->  
                <entrykey="id" value="id"/>
                <entrykey="mobile" value="mobile"/>
                <entrykey="email" value="email"/>
            </map>
        </property>
    </bean>

其中:

切記:查詢出來的字段名中間不能使用 _ (下劃線),否則獲取不到數據,如 cell_phone 需要 設置別名爲 cellPhone.

queryAttributeMapping是組裝sql用的查詢條件屬性,上述配置後,結合封裝成查詢sql就是 select *from userinfo where loginname=#username#

resultAttributeMapping是sql執行完畢後返回的結構屬性, key對應數據庫字段,value對應客戶端獲取參數。

如果要組裝多個查詢條件,需要加上下面這個,默認爲AND

<property name="queryType">

<value>OR</value>

      </property>  

 

二、配置用戶認證憑據轉化的解析器

也是在 deployerConfigContext.xml 中,找到credentialsToPrincipalResolvers,爲UsernamePasswordCredentialsToPrincipalResolver 注入 attributeRepository,那麼attributeRepository 就會被觸發並通過此類進行解析,紅色爲新添部分。

<propertyname="credentialsToPrincipalResolvers">
            <list>        
                <beanclass="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver">
                    <property name="attributeRepository"ref="attributeRepository"/>
                </bean>
                <beanclass="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver"/>
            </list>
 </property>

 三、配置InMemoryServiceRegistryDaoImpl屬性 registeredServices

修改 deployerConfigContext.xml 中的 org.jasig.cas.services.InMemoryServiceRegistryDaoImpl的 屬性 registeredServices。修改 registeredServices  allowedAttributes屬性值,將需要在客戶端顯示的列值加上。

<bean  id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl">
           <property name="registeredServices">
               <list>
                   <beanclass="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?)://.*" />
                       <propertyname="evaluationOrder" value="10000001" />
                       <propertyname="allowedAttributes"> // 客戶端需要使用的對象的屬性名稱
                               <list>
                                      <value>uid</value>
                                      <value>email</value>
                                      <value>mobile</value>
                                      <value>birth</value>
                                      <value>isMarry</value>
                                      <value>userno</value>
                                      <value>login_account</value>
                               </list>
                       </property>
                   </bean>

【提示】網上說此bean中的ignoreAttributes屬性默認是不添加用戶信息,查看了 CAS 3.5.2版本的 AbstractRegisteredService 源碼後,發現其默認值就是false,即:添加屬性後,客戶端就可見了

 

四、配置與客戶端交互的xml信息

修改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: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:iftest="${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端的工作就完成了,那麼如何在客戶端獲取這些信息呢?下面進行說明:

 

客戶端獲取用戶信息

cas client獲取用戶信息:

AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();
Map attributes = principal.getAttributes();
String email=attributes .get("email");

shiro集成後獲取用戶信息:

和shiro集成後,因爲cas client將casFilter交給了shiroFilter,所以在通過shiro對象時可以用戶信息的:

Subject subject = SecurityUtils.getSubject();
 
List list = subject.getPrincipals().asList();
String name = (String) list.get(0);
Map<String, Object> info = (Map<String, Object>)list.get(1);
 
String age = info.get("age").toString();


發佈了130 篇原創文章 · 獲贊 433 · 訪問量 45萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章