通过 Active Directory LDAP 使用 Spring-Security 进行身份验证
Posted
技术标签:
【中文标题】通过 Active Directory LDAP 使用 Spring-Security 进行身份验证【英文标题】:Authentication with Spring-Security via Active Directory LDAP 【发布时间】:2020-02-16 06:02:35 【问题描述】:我无法使用真实的活动目录进行身份验证,让我更好地解释一下我尝试使用 spring.io 提出的示例进行身份验证,没有问题,内部服务启动没有任何问题。 参考https://spring.io/guides/gs/authenticating-ldap/
我尝试通过插入我的活动目录的配置来修改下面的代码,但没有成功。您能否指导我或向我展示一个真实的案例,即在不使用示例中的内部服务的情况下建立真正的连接?我上网查了一下,发现都和官方的例子差不多,没有任何真实案例
@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()
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword");
错误显示: LDAP 处理期间发生未分类异常;嵌套异常为 javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0907C2,注释:为了执行此操作,必须在连接上成功绑定。,数据 0,v2580
【问题讨论】:
基于 LDAP 的做法是搜索 EntryDN,然后使用找到的 DN 和提供的密码执行身份验证。很奇怪,该指南显示使用 DN 合作伙伴作为首选。只有在极少数情况下,目录信息树才会是“平面”树。密码比较也是不好的做法。 通常也不允许匿名访问生产目录服务器,因此您需要一个“服务帐户”(特殊的 Bind-DN),可用于对目录服务器执行 LDAP 操作。跨度> 【参考方案1】:我在这里找到了一个样本,这很有用:
https://github.com/sachin-awati/Mojito/tree/master/webapp/src/main/java/com/box/l10n/mojito/security
如果在 Active Directory 查找期间未找到用户 - loadUserByUsername
,您可以选择实现UserDetailsContextMapperImpl
,它会覆盖mapUserFromContext
以创建UserDetails
对象。
@Component
public class UserDetailsContextMapperImpl implements UserDetailsContextMapper
@Override
public UserDetails mapUserFromContext(DirContextOperations dirContextOperations, String username, Collection<? extends GrantedAuthority> authorities)
UserDetails userDetails = null;
try
userDetails = userDetailsServiceImpl.loadUserByUsername(username);
catch (UsernameNotFoundException e)
String givenName = dirContextOperations.getStringAttribute("givenname");
String surname = dirContextOperations.getStringAttribute("sn");
String commonName = dirContextOperations.getStringAttribute("cn");
userDetails = userDetailsServiceImpl.createBasicUser(username, givenName, surname, commonName);
return userDetails;
确保您使用的是ActiveDirectoryLdapAuthenticationProvider
spring 安全类,因为与其他 LDAP 服务器相比,Active Directory 有自己的细微差别。您可能需要在安全配置类中使用 @EnableGlobalAuthentication
注释,因为您可以有多个 AuthenticationManagerBuilder
s,这会造成很多混乱。
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
ActiveDirectoryLdapAuthenticationProvider adProvider =
new ActiveDirectoryLdapAuthenticationProvider("domain.com", "ldap://primarydc.domain.com:389");
adProvider.setConvertSubErrorCodesToExceptions(true);
adProvider.setUseAuthenticationRequestCredentials(true);
auth.authenticationProvider(adProvider);
更多细节在这里: https://github.com/spring-projects/spring-security/issues/4324 https://github.com/spring-projects/spring-security/issues/4571
【讨论】:
【参考方案2】:是的,通过 LDAP 进行身份验证太痛苦了。为了能够对 AD 执行身份验证,您需要使用 ActiveDirectoryLdapAuthenticationProvider。 这是工作示例:
@Override
protected void configure(AuthenticationManagerBuilder auth)
ActiveDirectoryLdapAuthenticationProvider adProvider =
new ActiveDirectoryLdapAuthenticationProvider("domain.com", "ldap://localhost:8389");
adProvider.setConvertSubErrorCodesToExceptions(true);
adProvider.setUseAuthenticationRequestCredentials(true);
auth.authenticationProvider(adProvider);
为了节省您的时间,请阅读以下内容,这非常重要: AD authentication doc
【讨论】:
以上是关于通过 Active Directory LDAP 使用 Spring-Security 进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 LDAP over TLS 对 Active Directory 进行身份验证?
使用 SQL Server 2005 通过 LDAP 访问 Active Directory 角色成员资格
通过 Active Directory LDAP 使用 Spring-Security 进行身份验证
关于 SonarQube 和 Active Directory 之间的简单 Ldap 连接
通过 Spring Security 的 Active Directory 身份验证返回由 LDAP 引起的有效用户的错误凭据:错误代码 49