CAS SSO 4.0 单点登录返回更多用户信息

从cas server登录成功后,默认只能从cas server得到用户名。但程序中也可能遇到需要得到更多如姓名,手机号,email等更多用户信息的情况。
cas client拿到用户名后再到数据库中查询,的确可以得到关于该用户的更多信息。

但是如果用户登录成功后,直接从cas server返回给cas client用户的详细信息,这也是一个不错的做法。这个好处,尤其是在分布式中得以彰显,cas server可以把用户信息传递给各个应用系统,如果是上面那种做法,那么各个系统得到用户名后,都得去数据库中查询一遍,无疑是一件重复性工作。

一、首先需要配置属性attributeRepository:

WEB-INF目录找到 deployerConfigContext.xml文件,同时配置 attributeRepository 如下:

<bean  class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao" id="attributeRepository">
	<constructor-arg index="0" ref="dataSource"/>
	<constructor-arg index="1" value="select * from t_user where {0}"/>
	<property name="queryAttributeMapping">
		<map>
			<!--这里的key需写username和登录页面一致,value对应数据库用户名字段-->
			<entry key="username" value="loginname"/>
		</map>
	</property>
	<property name="resultAttributeMapping">
		<map>
			<!--key为对应的数据库字段名称,value为提供给客户端获取的属性名字,系统会自动填充值-->
			<entry key="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.

<property name="queryType">
	<value>OR</value>
</property> 
二、修改serviceRegistryDao

deployerConfigContext.xml中的 beans中id为serviceRegistryDao的属性 registeredServicesList。在 registeredServicesList中添加allowedAttributes属性的值。列出的每个值,在客户端就可以访问了。

<util:list id="registeredServicesList">
	<bean class="org.jasig.cas.services.RegexRegisteredService"
		  p:id="0" p:name="HTTP and IMAP" p:description="Allows HTTP(S) and IMAP(S) protocols"
		  p:serviceId="^(http?|https?|imaps?)://.*" p:evaluationOrder="10000001">
		  <!-- 添加该属性allowedAttributes -->
		  <property name="allowedAttributes">
			  <list>
				  <value>suid</value>
			  </list>
		  </property>
	</bean>
</util:list>
此步骤非常重要,可以看看org.jasig.cas.services.RegexRegisteredService的源码,其中的allowedAttributes是关键。


三、修改casServiceValidationSuccess.jsp

WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp.在server验证成功后,这个页面负责生成与客户端交互的xml信息,在默认的casServiceValidationSuccess.jsp中,只包括用户名,并不提供其他的属性信息,因此需要对页面进行扩展。如下:

<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="${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: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>

四、CAS Client获取用户信息


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

 
 

补充:自定义SQL查询用户信息

在步骤一,使用SQL比较单一,这样我就发现了类org.jasig.services.persondir.support.jdbc.NamedParameterJdbcPersonAttributeDao这个类中有DataSource和sql.但是我发现使用这个类我无法使用自定义查询SQL因为不能随便自己来传入参数,所以可以自己写类实现类org.jasig.services.persondir.support.AbstractDefaultAttributePersonAttributeDao。具体代码如下:

package org.jasig.cas.myself.persondir.support;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.sql.DataSource;

import org.jasig.services.persondir.IPersonAttributes;
import org.jasig.services.persondir.support.AbstractDefaultAttributePersonAttributeDao;
import org.jasig.services.persondir.support.CaseInsensitiveNamedPersonImpl;
import org.jasig.services.persondir.support.IUsernameAttributeProvider;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import com.google.common.collect.Lists;

public class MyNamedParameterJdbcPersonAttributeDao extends AbstractDefaultAttributePersonAttributeDao implements InitializingBean {

    private JdbcTemplate jdbcTemplate;

    private DataSource dataSource;
    private String sql;
    private IUsernameAttributeProvider usernameAttributeProvider;
    private Set<String> availableQueryAttributes = null;  // default
    private Set<String> userAttributeNames = null;  // default

    @Required
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Required
    public void setSql(String sql) {
        this.sql = sql;
    }
    
    @Required
    public void setUsernameAttributeProvider(IUsernameAttributeProvider usernameAttributeProvider) {
        this.usernameAttributeProvider = usernameAttributeProvider;
    }
    
    public void setAvailableQueryAttributes(Set<String> availableQueryAttributes) {
        this.availableQueryAttributes = Collections.unmodifiableSet(availableQueryAttributes);
    }
    
    @Required
    public void setUserAttributeNames(Set<String> userAttributeNames) {
        this.userAttributeNames = Collections.unmodifiableSet(userAttributeNames);
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public Set<String> getAvailableQueryAttributes() {
        return availableQueryAttributes;
    }

    @Override
    public Set<IPersonAttributes> getPeopleWithMultivaluedAttributes(Map<String, List<Object>> queryParameters) {
        String username = usernameAttributeProvider.getUsernameFromQuery(queryParameters);
        Map<String,List<Object>> mapOfLists = new HashMap<String,List<Object>>();
        Object suid = jdbcTemplate.queryForObject(sql, new RowMapper<Object>() {

            @Override
            public Object mapRow(ResultSet paramResultSet, int paramInt) throws SQLException {
                // TODO Auto-generated method stub
                return paramResultSet.getObject("SUID");
            }}, new Object[]{username,username,username});
        if(null != suid){
            mapOfLists.put("suid", Lists.newArrayList(suid));
        }
        return getResults(username, mapOfLists);
    }

    @Override
    public Set<String> getPossibleUserAttributeNames() {
        return userAttributeNames;
    }

    public Set<IPersonAttributes> getResults(String username, Map<String, List<Object>> attributes) {
        IPersonAttributes person = new CaseInsensitiveNamedPersonImpl(username, attributes);
        return Collections.singleton(person);
    }

}

然后在deployerConfigContext.xml文件做如下修改:


    <bean id="attributeRepository" class="org.jasig.cas.myself.persondir.support.MyNamedParameterJdbcPersonAttributeDao"> 
        <property name="dataSource" ref="dataSource"/>
        <property name="sql" value="select suid from login where NAME = ? or CELLPHONE = ? or EMAIL = ?" />
        <property name="usernameAttributeProvider" ref="usernameAttributeProvider"/>
        <property name="userAttributeNames">
            <value>suid</value>
        </property>
    </bean>

    <bean id="usernameAttributeProvider" class="org.jasig.services.persondir.support.SimpleUsernameAttributeProvider" />

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${cust.center.jdbc.driverClassName}" />
        <property name="jdbcUrl" value="${cust.center.jdbc.url}" />
        <property name="user" value="${cust.center.jdbc.username}" />
        <property name="password" value="${cust.center.jdbc.password}" />
        <property name="preferredTestQuery" value="SELECT 1"/>
        <property name="idleConnectionTestPeriod" value="18000"/>
        <property name="testConnectionOnCheckout" value="true"/>
    </bean>


这样自定义查询方式就完成了,也可以返回更多用户信息。当然我这是只返回一个多余信息。如果你需要返回多个,可以做相应的修改哈。

引用地址:http://blog.csdn.net/tch918/article/details/22102987?utm_source=tuicool


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值