CAS返回对象的更多属性Assertion.getPrincipal().getAttributes()
服务器,在返回给客户端用户信息时,默认只返回用户名(我们已经修改成ID).但有时我们需要更多的属性信息,如用户名。
则应做如下修改:
用户登录成功以后,CAS使用一个credentialsToPrincipalResolvers将credentials转成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以后,会将css:attributes中的属性解析出来,放到AttirubtePrincipal的attributes属性中去(或是放到Asseration的attributes中去,两个只会放一个)。
所以,组成上面的<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中的RegisteredServiceImpl的ignoreAttributes属性将决定是否添加attributes属性内容,默认为false:不添加,只有去掉这个配置,
cas server才会将获取的用户的附加属性添加到认证用的Principal的attributes中去。
然后即可以在页面上通过以下方式获取用户的其他属性:
<%
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);
%>