LDAP:在身份验证事件期间获取自定义值

Posted

技术标签:

【中文标题】LDAP:在身份验证事件期间获取自定义值【英文标题】:LDAP: fetch custom values during an authentication event 【发布时间】:2019-10-12 21:14:55 【问题描述】:

我让 Springboot 成功地针对 LDAP 进行身份验证,并将 CustomUserDetails 模型添加到视图中。

在身份验证活动期间,我还想带回其他详细信息,例如电子邮件、电话和城市。

根据这个SO answer 这是可能的,我认为this 也解决了这个问题。

尽管阅读了这两个答案,但我仍然不确定如何继续执行此操作 - 特别是关于第二个答案的第 2 步和第 3 步如何关联,以及电子邮件、城市和电话等详细信息的映射位置?

我的安全课:

安全

@SpringBootApplication
public class ApplicationSecurity extends WebSecurityConfigurerAdapter 

@Autowired
private UserDetailsService userDetailsService;

@Override
public void configure(HttpSecurity http) throws Exception 
    http
            .authorizeRequests()
                .anyRequest().fullyAuthenticated()
                .and()
            .formLogin()
                .defaultSuccessUrl("/newExhibit");


@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth
            .userDetailsService(userDetailsService)
            .and()
            .ldapAuthentication()
            .userDnPatterns("uid=0,ou=people")
            .groupSearchBase("ou=groups")
            .contextSource()
            .url("ldap://localhost:8389/dc=springframework,dc=org")
            .and()
            .passwordCompare()
            .passwordEncoder(passwordEncoder())
            .passwordAttribute("userPassword");

来自 test-server.ldif 的我的用户对象

dn: uid=abc123,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Tom Smith
sn: Smith
uid: abc123
userPassword: pass
mail: tom@contoso.com
mobile: +212 307 12345
st: CA

在this answer 之后我需要添加到身份验证 (a) contextsource 和 (b) userDetailsContextMapper?

我想最终将这些来自 ldap 的详细信息映射到我的 java 用户类。

更新

更新的 AuthenticationManagerBuilder

@SpringBootApplication
public class ApplicationSecurity extends WebSecurityConfigurerAdapter 

@Autowired
private UserDetailsService userDetailsService;

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth
        .userDetailsService(userDetailsService)
        .and()
        .ldapAuthentication()
        .userDnPatterns("uid=0,ou=people")
        .groupSearchBase("ou=groups")
        .contextSource()
        .userDetailsContextMapper(???) // what object in here and how initalised
        .url("ldap://localhost:8389/dc=springframework,dc=org")
        .and()
        .passwordCompare()
        .passwordEncoder(passwordEncoder())
        .passwordAttribute("userPassword");

【问题讨论】:

您只需要一个自定义的UserDetailsContextMapper 即可检索和设置自定义属性。 ContextSource 是由您配置 Spring Security 的方式创建的。 @M.Deinum 这个 UserDetailsContextMapper 会是什么样子? 查看您的 LDIF 文件,您实际上并不需要自定义映射器,但您可能会使用 InetOrgPersonContextMapper,所以 new InetOrgPersonContextMapper(),可能会成功。因为mailmobile 属性是在inetOrgPerson 的LDAP 模式中定义的。所以除非你真的有自定义属性,否则你真的不需要。 【参考方案1】:

查看您的 LDIF 文件,我看起来您正在尝试获取定义为 inetOrgPerson 一部分的属性。 Spring Security 有一个开箱即用的映射器InetOrgPersonContextMapper。这会将定义的属性映射到InetOrgPerson,这将充当所需的UserDetails

要进行配置,您只需创建一个新实例并将其连接到您的配置。

@SpringBootApplication
public class ApplicationSecurity extends WebSecurityConfigurerAdapter 


@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth
      .ldapAuthentication()
        .userDnPatterns("uid=0,ou=people")
        .groupSearchBase("ou=groups")
        .contextSource()
        .url("ldap://localhost:8389/dc=springframework,dc=org")
        .and()
        .userDetailsContextMapper(new InetOrgPersonContextMapper())
        .passwordCompare()
        .passwordEncoder(passwordEncoder())
        .passwordAttribute("userPassword");

这将相应地映射属性。当您使用 LDAP 时,您不需要注入 UserDetailsService,因为它会自动在下面配置 LdapUserDetailsService

【讨论】:

以上是关于LDAP:在身份验证事件期间获取自定义值的主要内容,如果未能解决你的问题,请参考以下文章

nginx_ldap_auth和自定义身份验证页面

Spring Security - LDAP 身份验证和数据库授权

是否可以在 Keycloak 中使用自定义身份验证逻辑?

是否可以在Keycloak中使用自定义身份验证逻辑?

使用LDAP登录模块进行Teiid VDB数据虚拟化的身份验证失败

在身份验证 Spring Security + WebFlux 期间抛出和处理自定义异常