CAS 实现站内单点登录及实现第三方 OAuth、OpenId 登录(三)

原创
2014/03/07 17:03
阅读数 2.4K

一、概括

    在大多数情况下,随着用户登录系统后,用户 ID、用户名、E-mail、用户头像等等基本信息,需要被使用直到用户退出系统。

    CAS Server 默认情况下,成功登录后,只会返回用户标示(通常是用户名)给 CAS Client。这时,各个 Client 还需要根据用户标示,去查询用户其它信息,这时如果如果 CAS Server 统一将这些信息返回给 Client 了,各个 Client 就无需再次进行查询了。

二、配置

    修改 deployerConfigContext.xml

  1. 修改

    <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

  2. 修改

    <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” 对结果进行过滤

  3. 假设是多条件登录,则需要修改

    <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,以方便根据一个唯一的用户值去查询更多的用户信息。

  4. 在模板文件 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、手机号码等等

展开阅读全文
打赏
0
2 收藏
分享
加载中
泥煤。。。。
2014/04/11 17:15
回复
举报
更多评论
打赏
1 评论
2 收藏
0
分享
返回顶部
顶部