CAS返回對象的更多屬性Assertion.getPrincipal().getAttributes()

wangjianme 12年前發布 | 134K 次閱讀 CAS SSO Assertion OpenID/單點登錄SSO

服務器,在返回給客戶端用戶信息時,默認只返回用戶名(我們已經修改成ID.但有時我們需要更多的屬性信息,如用戶名。

則應做如下修改:

用戶登錄成功以后,CAS使用一個credentialsToPrincipalResolverscredentials轉成Principal對象,此對象只有一個實現類如下.
SimplePrincipal的構造方法接收兩個參數,一個是用戶的id,一個為用戶的其他屬性。用戶的ID默認為用戶登錄時使用的用戶名,前面第4點已經講過如何將用戶的name換成用戶的id返回給客戶端。為了給客戶端返回更多的屬性,我們必須要給Principal的構造方法傳遞第二個參數,它是一個Map<String,Object>類型。

具體代碼如下:

package cn.itcast.pubs;

import java.util.HashMap;

import java.util.Map;


import javax.sql.DataSource;

import org.jasig.cas.authentication.principal.Credentials;

import org.jasig.cas.authentication.principal.CredentialsToPrincipalResolver;

import org.jasig.cas.authentication.principal.Principal;

import org.jasig.cas.authentication.principal.SimplePrincipal;

import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;

import org.springframework.jdbc.core.JdbcTemplate;

public class MyCredentialsToPrincipalResolver implements CredentialsToPrincipalResolver {

private DataSource dataSource;//查詢數據庫用

@Override

public Principal resolvePrincipal(Credentials credentials) {

System.err.println("將憑據轉換成被代理人:"+credentials);

UsernamePasswordCredentials up = //強制類型轉換

(UsernamePasswordCredentials) credentials;

String name = up.getUsername();

String pwd  = up.getPassword();

String sql = "select id from users2 where u2_name=? and u2_pwd=?"; //查詢id

String id  = null;

try{

id=new JdbcTemplate(getDataSource()).queryForObject(sql, String.class, name,pwd);

if(id!=null){

//封裝其他信息

Map<String,Object> attrs = new HashMap<String,Object>();

attrs.put("username",name);

attrs.put("pwd",pwd);

Principal p = new SimplePrincipal(id,attrs);//封裝成包含id的Principal對象

System.err.println("生成的屬性值是::"+attrs);

return p;

}

}catch(Exception e){

e.printStackTrace();

}

return null;

}


@Override

public boolean supports(Credentials credentials) {

boolean boo =  //判斷是否是用戶和密碼憑據 

UsernamePasswordCredentials.class.isAssignableFrom(credentials.getClass());

return boo;

}

public DataSource getDataSource() {

return dataSource;

}


public void setDataSource(DataSource dataSource) {

this.dataSource = dataSource;

}

}


但,它并不會馬上顯示到客戶端,如果要顯示到客戶端,因為服務器驗證成功以后,是通過xml形式將結果傳遞給客戶端的,xml的生成由casServiceValidationSuccess.jsp文件負責。它的具體構造應該是以下形式:

<cas:serviceResponse

    xmlns:cas='http://www.yale.edu/tp/cas'>

    <cas:authenticationSuccess>

       <cas:user>U001</cas:user>

       <cas:attributes>

              <cas:pwd>1234</cas:pwd>

              <cas:username>Jack</cas:username>

       </cas:attributes>

    </cas:authenticationSuccess>

</cas:serviceResponse>

在上面的代碼中cas:attributes元素是筆者添加的客戶端的的Filter在接收到上述的XML以后,會將cssattributes中的屬性解析出來,放到AttirubtePrincipalattributes屬性中去(或是放到Asserationattributes中去,兩個只會放一個)。

 

所以,組成上面的<cas :attributes>元素中的內容,就成了如何傳遞更多屬性的關鍵,在修改了MyCredentialsToPrincipalResolver的代碼以后,然后還必須要修改casServiceValidationSuccess.jsp的代碼如下:

<%@ page session="false" contentType="text/xml; charset=UTF-8"%><%@ taglib

    prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@ taglib

    uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%><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="${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:attributes>

           <c:forEach

               items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}"

              var="attr">

              <cas:${attr.key}>${attr.value}</cas:${attr.key}>

           </c:forEach>

       </cas:attributes>

    </cas:authenticationSuccess>

</cas:serviceResponse>

 

然后修改deployerConfigContext.xml文件將最后一個配置項serviceRegistryDao中的所有屬性全部刪除或是注銷。

這個bean中的RegisteredServiceImplignoreAttributes屬性將決定是否添加attributes屬性內容,默認為false:不添加,只有去掉這個配置,
cas server
才會將獲取的用戶的附加屬性添加到認證用的Principalattributes中去。

 

然后即可以在頁面上通過以下方式獲取用戶的其他屬性:

    <%

       Assertion assertion = AssertionHolder.getAssertion();

       AttributePrincipal ap =  assertion.getPrincipal();   //獲取AttributePrincipal對象,這是客戶端對象

       String name = ap.getName();

       Map<String,Object> att = ap.getAttributes();     //獲取屬性值,為一個Map類型。

       out.print("<br/>"+name);

       out.print("<br/>"+att);

%>



 本文由用戶 wangjianme 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!