一、概括
在大多数情况下,随着用户登录系统后,用户 ID、用户名、E-mail、用户头像等等基本信息,需要被使用直到用户退出系统。
CAS Server 默认情况下,成功登录后,只会返回用户标示(通常是用户名)给 CAS Client。这时,各个 Client 还需要根据用户标示,去查询用户其它信息,这时如果如果 CAS Server 统一将这些信息返回给 Client 了,各个 Client 就无需再次进行查询了。
二、配置
修改 deployerConfigContext.xml
修改
<bean id="attributeRepositoryDao" class="com.buession.cas.service.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao"> <property name="jdbcTemplate" ref="slaveJdbcTemplate" /> <property name="queryTemplate" value="SELECT * FROM `member` WHERE {0} LIMIT 1" /> <property name="queryAttributeMapping"> <map> <entry key="username" value="username" /> </map> </property> <property name="resultAttributeMapping"> <map> <!-- key 对应数据库字段名,value 为查询结果转换为 Map 的 key --> <entry key="id" value="id" /> <entry key="username" value="username" /> <entry key="email" value="email" /> ... ... </map> </property> </bean>
SQL 语句最终会转换为: SELECT * FROM `member` WHERE username(queryAttributeMapping Map Entry 中的 value) = '登录表单中的 username' LIMIT 1
修改
<bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl"> <property name="registeredServices"> <list> <bean class="org.jasig.cas.services.RegexRegisteredService"> ... ... <property name="ignoreAttributes" value="true" /> <!-- 或者 --> <property name="allowedAttributes"> <list> <!-- value 的值对应 attributeRepositoryDao resultAttributeMapping 的 entry 的 value 属性 只有这里定义了元素,才会真正从 resultAttributeMapping 返回给 client --> <value>id</value> <value>username</value> <value>email</value> ... ... </list> </property> </bean> ... ... </list> </property> </bean>
当 ignoreAttributes 为 true 时,则返回获取到的全部用户信息给 CAS Client,而不根据 “allowedAttributes” 对结果进行过滤
假设是多条件登录,则需要修改
<bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl"> ... ... <property name="authenticationHandlers"> <list> <bean class="com.domain.authentication.handler.DatabaseAuthenticationHandler"> <property name="jdbcTemplate" ref="slaveJdbcTemplate" /> <property name="sql" value="SELECT `username`, ...... FROM `member` WHERE `username` = ? OR `email` = ? OR `mobile` = ?" /> <property name="passwordEncoder" ref="passwordEncoder" /> </bean> </list> </property> </bean> class DatabaseAuthenticationHandler extends com.buession.cas.authentication.handler.support.DatabaseQueryAuthenticationHandler { @Override protected boolean authenticateUsernamePasswordInternal(UsernamePasswordCredentials credentials) throws AuthenticationException { ... ... try { ... ... if (valid(username, password, r, passwordEncoder) == true) { credentials.setUsername((String) r.get("username")); return ture; } } catch (IncorrectResultSizeDataAccessException e) { } return false; } }
登录验证 SQL 语句中,你必需得返回与 queryAttributeMapping Map 中 value 一致的字段,然后在 DatabaseAuthenticationHandler.authenticateUsernamePasswordInternal 中验证成功后,重新赋值给 UsernamePasswordCredentials 的 username,以方便根据一个唯一的用户值去查询更多的用户信息。
在模板文件 WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp 中添加
<c:if test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes) > 0}"> <cas:attributes> <c:forEach var="r" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}"> <cas:${fn:escapeXml(r.key)}>${fn:escapeXml(r.value)}</cas:${fn:escapeXml(r.key)}> </c:forEach> </cas:attributes> </c:if>
三、结果
注意:cas:user 是登录表单中输入的 username,可能是用户名、e-mail、手机号码等等