Spring-boot LDAP customize UserDetails
我在spring-boot应用程序中使用LDAP身份验证(基于注释的配置)。我想自定义UserDetails对象。默认的UserDetails实现是LdapUserDetailsImpl。我想扩展此类,添加一些额外的Iterfaces并绑定到spring-security中。
我的配置类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | @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对象):
1 2 3 4 5 6 7 8 | @Component("activeUserAccessor") public class ActiveUserAccessorImpl implements ActiveUserAccessor { public UserDetails getActiveUser() { return (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); } } |
谢谢您的帮助。
我的解决方案:
1。创建自定义UserDetailsContextMapper:
1 2 3 4 5 6 7 8 9 10 | @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。使用LdapAuthenticationProviderConfigurer绑定UserDetailsContextMapper:
1 2 3 4 5 6 | 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()中返回扩展类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 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(); } } |