cas4.2.7登陆后从不同的表中查数据

CAS 375 2017-09-19 10:52

cas后在登陆成功后,会返回一些数据给客户端,由于是多个系统整合跳转到cas登陆,需要根据不同用户类型,从不同的用户表中查询用户数据返回给客户端。下面来简单介绍一下实现方法:

1.找到deployerConfigContext.xml,配置attributeRepository,增加了一个attributeRepository_visitor的bean

原来的bean:

<bean id="attributeRepository" class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao" >
        <constructor-arg index="0" ref="dataSource"/>
        <constructor-arg index="1">
            <value>select id,username,realname,uuid from sysuser where {0}</value>
        </constructor-arg>
        <property name="queryAttributeMapping">
            <map>
                <!-- queryAttributeMapping username是登录框的id,value数据库字段 -->
                <entry key="username" value="username"/>
            </map>
        </property>
        <property name="resultAttributeMapping">
            <map>
                <!-- resultAttributeMapping key是数据库中字段,value是返回给客户端的属性名-->
                <entry key="id" value="id" />
                <entry key="username" value="username" />
                <entry key="realname" value="realname" />
                <entry key="uuid" value="uuid" />
            </map>
        </property>
    </bean>

新增的bean:

<bean id="attributeRepository_visitor" class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao" >
        <constructor-arg index="0" ref="dataSource"/>
        <constructor-arg index="1">
            <value>select id,username,realname,uuid from sysuser1 where {0}</value>
        </constructor-arg>
        <property name="queryAttributeMapping">
            <map>
                <!-- queryAttributeMapping username是登录框的id,value数据库字段 -->
                <entry key="username" value="username"/>
            </map>
        </property>
        <property name="resultAttributeMapping">
            <map>
                <!-- resultAttributeMapping key是数据库中字段,value是返回给客户端的属性名-->
                <entry key="id" value="id" />
                <entry key="username" value="username" />
                <entry key="realname" value="realname" />
                <entry key="uuid" value="uuid" />
            </map>
        </property>
    </bean>

2.找到PersonDirectoryPrincipalResolver类,仿照attributeRepository的定义方法

(1)新增attributeRepository_visitor 的定义

@NotNull
protected IPersonAttributeDao attributeRepository_visitor = new StubPersonAttributeDao(new HashMap<String, List<Object>>());

(2)增加attributeRepository_visitor的赋值方法

@Autowired
    public final void attributeRepository_visitor(@Qualifier("attributeRepository_visitor")
                                             final IPersonAttributeDao attributeRepository_visitor) {
        this.attributeRepository_visitor = attributeRepository_visitor;
    }

(3)修改此类中的retrievePersonAttributes方法

protected Map<String, List<Object>> retrievePersonAttributes(final String principalId, final  Credential credential) {

        UsernamePasswordCredential credential1 = (UsernamePasswordCredential)credential;

        String usertype = credential1.getUsertype();

        IPersonAttributes personAttributes = null;
        if(usertype.equals("1")){
            personAttributes = this.attributeRepository_visitor.getPerson(principalId);
        }else {
            personAttributes = this.attributeRepository.getPerson(principalId);
        }

        final Map<String, List<Object>> attributes;

        if (personAttributes == null) {
            attributes = null;
        } else {
            attributes = personAttributes.getAttributes();
        }
        return attributes;

    }

这里的usertype是我自己定义的,在登陆页面定义一个下拉选择框,然后把值传到后台判断,下面介绍传这个值的方法:

3.定义usertype

(1)找到casLoginView.jsp页面,也就是我们的登陆页面,定义一个下拉框,我的页面已经自己重新写过了

<select name="usertype">
          <option value="0" selected>普通用户</option>
          <option value="1">游客</option>
 </select>

(2)找到login-webflow.xml页面,在viewLoginForm中,增加usertype

<view-state id="viewLoginForm" view="casLoginView" model="credential">
        <binder>
            <binding property="username" required="true"/>
            <binding property="password" required="true"/>
            <binding property="usertype" required="true"/>
            <!--
            <binding property="rememberMe" />
            -->
        </binder>
        <on-entry>
            <set name="viewScope.commandName" value="'credential'"/>
            <!--
            <evaluate expression="samlMetadataUIParserAction" />
            -->
        </on-entry>
        <transition on="submit" bind="true" validate="true" to="realSubmit"/>
    </view-state>

(3)找到UsernamePasswordCredential类(相当于user的实体类),定义usertype:

    @NotNull
    @Size(min=1, message = "required.usertype")
    private String usertype;

生成set和get方法

public final String getUsertype() {
        return this.usertype;
}
public final void setUsertype(final String usertype) {
        this.usertype = usertype;
}

这样我们就可以在PersonDirectoryPrincipalResolver类中的retrievePersonAttributes方法里面得到usertype了。 做完了这些,我们就可以从不同的表中来获取用户信息返回给用户了。 当然,登陆验证的时候我们也需要从不同的表中获取数据,下面来实际操作一下:

4.登陆验证时从不同的表中获取user数据

(1)找到QueryDatabaseAuthenticationHandler类,在原来的查询sql上,重新定义查询sql:

原来的:

@NotNull
private String sql;

新定义的:

@NotNull
@Value("${cas.jdbc.authn.query.sql.visitor}")
private String sql_visitor;

(2)找到cas.properties,配置cas.jdbc.authn.query.sql.visitor

cas.jdbc.authn.query.sql.visitor=select password from sysuser1 where username=? and isdel=0

(3)修改此类中的authenticateUsernamePasswordInternal方法:

@Override
    protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential)
            throws GeneralSecurityException, PreventedException {

        final String usertype= credential.getUsertype();
        if(StringUtils.isNotEmpty(usertype)){
            if(usertype.equals("1")){
                this.sql = this.sql_visitor;
            }
        }

        if (StringUtils.isBlank(this.sql) || getJdbcTemplate() == null) {
            throw new GeneralSecurityException("Authentication handler is not configured correctly");
        }

        final String username = credential.getUsername();
        final String encryptedPassword = this.getPasswordEncoder().encode(credential.getPassword());
        try {
            final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
            if (!dbPassword.equals(encryptedPassword)) {
                throw new FailedLoginException("Password does not match value on record.");
            }
        } catch (final IncorrectResultSizeDataAccessException e) {
            if (e.getActualSize() == 0) {
                throw new AccountNotFoundException(username + " not found with SQL query");
            } else {
                throw new FailedLoginException("Multiple records found for " + username);
            }
        } catch (final DataAccessException e) {
            throw new PreventedException("SQL exception while executing query for " + username, e);
        }
        return createHandlerResult(credential, this.principalFactory.createPrincipal(username), null);
    }

到此就可以了。 希望能帮助到大家!

文章评论