【问题标题】:Spring-boot LDAP customize UserDetailsSpring-boot LDAP 自定义 UserDetails
【发布时间】:2015-05-14 11:39:05
【问题描述】:

我在 spring-boot 应用程序中使用 LDAP 身份验证(基于注释的配置)。我想自定义 UserDetails 对象。默认 UserDetails 实现是 LdapUserDetailsImpl。我想扩展这个类并添加一些额外的 iterfaces 并绑定到 spring-security 中。 我的配置类:

@Configuration
protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter { 
    @Autowired
    private UserService userService;
    @Autowired
    private Environment env;

    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        AuthMethod authMethod = AuthMethod.valueOf(env.getRequiredProperty("auth_method"));
        switch (authMethod) {
            case LDAP:
                auth.ldapAuthentication()
                    .userDnPatterns(env.getRequiredProperty("ldap.user_dn_patterns"))
                    .groupSearchBase(env.getRequiredProperty("ldap.group_search_base"))
                    .contextSource()
                    .url(env.getRequiredProperty("ldap.url"));
                break;
            default:
                auth.userDetailsService(userService);
                break;
        }

    }

    @Bean
    public LdapContextSource contextSource () {
        LdapContextSource contextSource= new LdapContextSource();
        contextSource.setUrl(env.getRequiredProperty("ldap.url"));
        contextSource.setUserDn(env.getRequiredProperty("ldap.user"));
        contextSource.setPassword(env.getRequiredProperty("ldap.password"));
        contextSource.afterPropertiesSet();
        return contextSource;
    }
}

UserService 是自定义的身份验证方法(它是数据库/jpa 身份验证)。 UserDetails 访问器(当 auth 方法是 LDAP 时,它返回 LdapUserDetailsImpl 对象):

    @Component("activeUserAccessor")
public class ActiveUserAccessorImpl implements ActiveUserAccessor
{
    public UserDetails getActiveUser()
    {
        return (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }
}

感谢您的帮助。

【问题讨论】:

    标签: spring spring-security ldap spring-boot spring-security-ldap


    【解决方案1】:

    我的解决方案:

    1.创建自定义UserDetailsContextMapper:

        @Bean
        public UserDetailsContextMapper userDetailsContextMapper() {
            return new LdapUserDetailsMapper() {
                @Override
                public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
                    UserDetails details = super.mapUserFromContext(ctx, username, authorities);
                    return new CustomLdapUserDetails((LdapUserDetails) details, env);
                }
            };
        }
    

    2.将UserDetailsContextMapper与LdapAuthenticationProviderConfigurer绑定:

      auth.ldapAuthentication()
          .userDetailsContextMapper(userDetailsContextMapper())
          .userDnPatterns(env.getRequiredProperty("ldap.user_dn_patterns"))
          .groupSearchBase(env.getRequiredProperty("ldap.group_search_base"))
          .contextSource()
          .url(env.getRequiredProperty("ldap.url"));
    

    3.实现CustomLdapUserDetails(现在只改变isEnabled方法)。您可以在 CustomLdapUserDetails 中添加一些额外的接口、方法,并在 ActiveUserAccessor.getActiveUser() 中返回扩展类。

    public class CustomLdapUserDetails implements LdapUserDetails {
    private static final long serialVersionUID = 1L;
    
    private LdapUserDetails details;
    private Environment env;
    
    public CustomLdapUserDetails(LdapUserDetails details, Environment env) {
        this.details = details;
        this.env = env;
    }
    
    public boolean isEnabled() {
        return details.isEnabled() && getUsername().equals(env.getRequiredProperty("ldap.username"));
    }
    
    public String getDn() {
        return details.getDn();
    }
    
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return details.getAuthorities();
    }
    
    public String getPassword() {
        return details.getPassword();
    }
    
    public String getUsername() {
        return details.getUsername();
    }
    
    public boolean isAccountNonExpired() {
        return details.isAccountNonExpired();
    }
    
    public boolean isAccountNonLocked() {
        return details.isAccountNonLocked();
    }
    
    public boolean isCredentialsNonExpired() {
        return details.isCredentialsNonExpired();
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-08-06
      • 2012-01-29
      • 2016-12-22
      • 2019-08-22
      • 1970-01-01
      • 2013-02-18
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多