从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.
二、修改serviceRegistryDao<property name="queryType"> <value>OR</value> </property>
deployerConfigContext.xml中的 beans中id为serviceRegistryDao的属性 registeredServicesList。在 registeredServicesList中添加allowedAttributes属性的值。列出的每个值,在客户端就可以访问了。
此步骤非常重要,可以看看org.jasig.cas.services.RegexRegisteredService的源码,其中的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>
三、修改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
CAS SSO 4.0 单点登录返回更多用户信息
最新推荐文章于 2021-12-31 17:18:16 发布