spring-security 如何在使用多个AuthenticationProvider时拥有相同类型的User对象?

yqyhoc1h  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(160)

我的服务器中有两个正在工作的AuthenticationProvider:

@Bean
public AuthenticationManager authenticationManager(final DataSource dataSource, final ContextSource contextSource,
    final ObjectPostProcessor<Object> objectPostProcessor) throws Exception {
    final AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(objectPostProcessor);
    auth.ldapAuthentication()
        .contextSource((BaseLdapPathContextSource) contextSource)
        .userSearchFilter("(| (sAMAccountName={0}))");
    auth.jdbcAuthentication()
        .passwordEncoder(new BCryptPasswordEncoder())
        .dataSource(dataSource)
        .usersByUsernameQuery("select username, password, enabled from Users where lower(username) = lower(?)")
        .authoritiesByUsernameQuery("select username, role from UserRoles where lower(username) = lower(?)");
    return auth.build();
}

一旦用户登录,我就通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()访问他们的数据(对没有登录或匿名登录进行适当的检查)。对于JDBC登录,主体是一个org.springframework.security.core.userdetails.User对象,对于LDAP,主体是一个org.springframework.security.ldap.userdetails.LdapUserDetailsImpl对象。我希望最终对两个提供者使用相同的自定义User类,它将包含一些额外的数据(全名、头像等)。
我应该在哪里添加这个自定义行为呢?我 * 可能 * 会在第一次访问原始Principal时替换它,但这似乎很笨拙,而且容易出错,以防有人跳过我的代码。
编辑:我在ldapAuthentication上找到了userDetailsContextMapper(UserDetailsContextMapper),但是对于jdbcAuthentication,等价的(?)UserDetailsService(或UserDetailsManager)是直接在配置器的构造器中设置的。这些是否允许我定制生成的用户对象,如果可以,我如何在jdbcAuthentication上设置一个?

liwlm1x9

liwlm1x91#

我认为JdbcUserDetailsManagerConfigurer没有配置返回类型的方法。
您可以创建自己的UserDetailsService并使用它来代替auth.jdbcAuthentication()...,如下所示:

@Bean
public AuthenticationManager authenticationManager(final DataSource dataSource, final ContextSource contextSource,
    final ObjectPostProcessor<Object> objectPostProcessor, UserDetailsService myUserDetailsService) throws Exception {
    final AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(objectPostProcessor);
    auth.ldapAuthentication()
        .contextSource((BaseLdapPathContextSource) contextSource)
        .userSearchFilter("(| (sAMAccountName={0}))");
    auth.userDetailsService(myUserDetailsService)
        .passwordEncoder(new BcryptPasswordEncoder());
    return auth.build();
}

这样,您就可以完全控制UserDetailsService的返回类型。

相关问题