CAS學習筆記(三)—— SERVER登陸後用戶信息的返回

一旦CAS SERVER驗證成功後,咱們就會跳轉到客戶端中去。跳轉到客戶端去後,你們想想,客戶端總要獲取用戶信息吧,否則客戶端是怎麼知道登陸的是哪一個用戶。那麼客戶端要怎麼獲取用戶信息呢?html

其實驗證成功,跳轉客戶端這個過程當中,CAS SERVER 會返回登陸的相關信息給客戶端,客戶端只要進行獲取,就能知道登陸的具體是哪一個用戶了。不過CAS 默認只返回用戶帳號給客戶端,那麼怎麼定義CAS SERVER返回的信息呢? 這就是本篇具體講解的內容了,你們聽我慢慢道來。java

 

相關接口                                                               

在開始時,咱們先了解下有關相關的幾個接口mysql

  • Credentials
  • Principal
  • IPersonAttributeDao
  • PrincipalResolver

 

Credentials                                                    

   Credentials (org.jasig.cas.authentication.Credentials)接口,咱們在上一篇其實有使用過,咱們當時有用過一個叫 UsernamePasswordCredential 的類,就是實現了Credentials接口。這個接口是用來定義咱們登陸頁上輸入的認證信息的,好比用戶名、密碼、驗證碼等,能夠理解爲用戶認證的相關憑據。web

 

Principal                                                     

  Principal (org.jasig.cas.authentication.principal.Principal) 接口,這個主要是用來保存用戶認證後的用戶信息,信息保存在一個Map中。sql

 

IPersonAttributeDao                                              

  IPersonAttributeDao (org.jasig.services.persondir.IPersonAttributeDao) 接口,這個是用來定義咱們須要返回給客戶端相關信息的接口,CAS SERVER 默認有提供許多實現,好比數據庫

  • LdapPersonAttributeDao :經過查詢 LDAP 目錄 ,來返回信息
  • SingleRowJdbcPersonAttributeDao : 經過JDBC SQL查詢,來返回信息

等等,還有許多,你們能夠參考源碼中的實現,CAS SERVER 提供了各類功能的實現,有時候咱們能夠直接使用這個現成的就好了。app

 

PrincipalResolver                                                 

  PrincipalResolver(org.jasig.cas.authentication.principal.PrincipalResolver) 接口,上面有說到 Credentials 是從登陸頁面上進行獲取相關用戶信息的。那麼認證成功後,怎麼把Credentials裏面的信息轉換到 Principal  中呢,這就是這個接口的做用了。因爲認證自己是沒有返回用戶信息的,只是肯定認證是經過仍是沒有經過。這時還要用到咱們上面的IPersonAttributeDao 接口,在這接口中咱們就能夠定義咱們須要返回的信息了。webapp

這接口中有兩個方法jsp

  • resolve : 解析Credentials中的信息,返回 Principal 接口
  • supports : 判斷Credentials 是否支持 Principal 協議。

ps: 在3.x版本中沒有 PrincipalResolver接口,對應的是CredentialsToPrincipalResolver, PrincipalResolver這個是在4.0版本中加入的,你們要注意。ide

 

流程                                           

 相關接口講解後,你們應該對怎麼返回信息有個大概的思路了。沒錯就是實現上面所說的 IPersonAttributeDao 、PrincipalResolver 接口 。下面根據代碼講解下具體的一個流程:

首先打開 deployerConfigContext.xml 文件,看下面的定義:

複製代碼
 <!--
       | Resolves a principal from a credential using an attribute repository that is configured to resolve
       | against a deployer-specific store (e.g. LDAP).
       -->
    <bean id="primaryPrincipalResolver"
          class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
        <property name="attributeRepository" ref="attributeRepository" />
    </bean>

    <!--
    Bean that defines the attributes that a service may return.  This example uses the Stub/Mock version.  A real implementation
    may go against a database or LDAP server.  The id should remain "attributeRepository" though.
    +-->
    <bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"
            p:backingMap-ref="attrRepoBackingMap" />
    
    <util:map id="attrRepoBackingMap">
        <entry key="uid" value="uid" />
        <entry key="eduPersonAffiliation" value="eduPersonAffiliation" /> 
        <entry key="groupMembership" value="groupMembership" />
    </util:map>
複製代碼

 

//PersonDirectoryPrincipalResolver 部分源碼

複製代碼
public final Principal resolve(final Credential credential) {
        logger.debug("Attempting to resolve a principal...");
      
        String principalId = extractPrincipalId(credential);  //extractPrincipalId 方法從credential中抽取id

       //省略...
        final IPersonAttributes personAttributes = this.attributeRepository.getPerson(principalId);  //根據IPersonAttributeDao 中的getPerson 獲取返回的屬性
        final Map<String, List<Object>> attributes;

       //最終返回 Principal 
        return new SimplePrincipal(principalId, convertedAttributes);
    }    
複製代碼

 

 

 具體流程:

1.從上面的deployerConfigContext.xml 配置咱們能夠看到,CAS 默認配置了一個叫作 PersonDirectoryPrincipalResolver 的類,在 這個類的 resolve  方法中有調用 extractPrincipalId 這個方法,這個方法傳入一個 Credentials 類型的參數,默認調用的是Credentials  的getId() 方法,CAS默認是返回用戶的userName,即登陸帳號。不過getId()  這個方法的實現咱們能夠在上一章中指定的UsernamePasswordCredential 類中自定義,通常是定義成返回用戶的userId或者其餘惟一鍵,由於咱們若是知道了用戶的userId,那麼就能夠根據這個從數據庫中查詢中用戶的一些具體信息了,進而就能夠組成咱們須要返回的信息。

 

2. 繼續往下看源碼,接着在 PersonDirectoryPrincipalResolver  中有注入一個 attributeRepository 屬性,這個就是上面的IPersonAttributeDao 接口,而後在resolve方法中調用了 IPersonAttributeDao 接口 的getPerson方法,還傳入了一個參數principalId,其實這個傳入的參數就是咱們上面 getId() 返回的值。

 

因此其實咱們只要實現咱們須要的 IPersonAttributeDao  就能夠了。 下面給一個簡單的IPersonAttributeDao  例子: 

 

複製代碼
public class BlogStubPersonAttributeDao extends StubPersonAttributeDao {

    @Override
    public IPersonAttributes getPerson(String uid) {
        
        Map<String, List<Object>> attributes = new HashMap<String, List<Object>>();
        attributes.put("userid", Collections.singletonList((Object)uid));
        attributes.put("cnblogUsername", Collections.singletonList((Object)"http://www.cnblogs.com/vhua"));
        attributes.put("cnblogPassword", Collections.singletonList((Object)"123456"));
        attributes.put("test", Collections.singletonList((Object)"test"));
        return new AttributeNamedPersonImpl(attributes);
    }
    
}
複製代碼

 

這邊傳入的uid 默認是用戶的登陸名,咱們這邊沒有作修改,直接用默認的。

這邊是隻是測試用,因此就直接寫死了,實際開發確定是須要在數據庫或者LDAP中進行查詢後,而後組裝成須要的信息 。

 

而後在 deployerConfigContext.xml 中修改

複製代碼
<bean id="primaryPrincipalResolver"
          class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
        <property name="attributeRepository" ref="attributeRepository" />
    </bean>
<!-- 修改前 --> <bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao" p:backingMap-ref="attrRepoBackingMap" /> <util:map id="attrRepoBackingMap"> <entry key="uid" value="uid" /> <entry key="eduPersonAffiliation" value="eduPersonAffiliation" /> <entry key="groupMembership" value="groupMembership" /> </util:map> <!-- 修改前 end-->
<!--修改後--> <bean id="attributeRepository" class="org.jasig.services.persondir.support.BlogStubPersonAttributeDao" /> <!--修改後 end-->
複製代碼

 

 

3. 修改完成後,咱們還須要在 casServiceValidationSuccess.jspcas-server-webapp\src\main\webapp\WEB-INF\view\jsp\protocol\2.0\casServiceValidationSuccess.jsp)

添加一段代碼(下面紅色部分):

複製代碼
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
    <cas:authenticationSuccess>
        <cas:user>${fn:escapeXml(assertion.primaryAuthentication.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> <!-- 這段 end-- >

<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>
複製代碼

 

 

4. 接下來 在客戶端設置信息的接收,咱們直接在index.jsp中測試一下:

Java中能夠經過下面的方式獲取

AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();

Map attributes = principal.getAttributes();

String xxx=attributes .get("xxx");

...

 

複製代碼
<!DOCTYPE html">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>返回值測試</title>
</head>
<body>

    <% 
    request.setCharacterEncoding("UTF-8");
    AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
    Map attributes = principal.getAttributes();
    String userid=(String)attributes.get("userid"); 
    String cnblogUsername = (String)attributes.get("cnblogUsername"); 
    String cnblogPassword = (String)attributes.get("cnblogPassword"); 
    String test=(String)attributes.get("test"); 
    
    %>
    <div>飛奔的蝸牛博客:返回值演示</div>
    <ul>
        <li>userid:<%= userid%></li>
        <li>username:<%= cnblogUsername%></li>
        <li>password:<%= cnblogPassword%></li>
        <li>test:<%= test%></li>
    </ul>
</body>
</html>
複製代碼

 

 

效果                                           

好了,咱們登陸運行看看結果。

 

 

你們看到沒,已經獲取成功了,在CAS SERVER那邊設置的信息,咱們正常獲取到了 。你們能夠根據業務的須要,返回相關的信息。而後在客戶端進行操做。

轉自:http://www.cnblogs.com/vhua/p/cas_4.html

相關文章
相關標籤/搜索