java - 使用 ActiveDirectoryLdapAuthenticationProvider 时检索 UserDetailsManager
问题描述
我希望我的应用程序的用户能够更改他们的密码。后台的身份验证提供程序是 Active Directory 服务器。
身份验证本身正在工作,尽管我在检索UserDetailsManager
允许我更改用户密码的实例时遇到问题。
这是我的安全配置:
@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) {
authManagerBuilder.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
@Bean
public AuthenticationManager authenticationManager(
AuthenticationProvider authenticationProvider) {
return new ProviderManager(Collections.singletonList(authenticationProvider));
}
@Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
LOGGER.info("AD provider for domain {} on {}:{}", adDomain, adHost, adPort);
ActiveDirectoryLdapAuthenticationProvider provider =
new ActiveDirectoryLdapAuthenticationProvider(adDomain, "ldap://" + adHost + ":" + adPort);
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
provider.setUserDetailsContextMapper(userContextMapper);
return provider;
}
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
@Bean("adUserDetailsManager")
public UserDetailsManager getUserDetailsManager(ContextSource contextSource) {
return new LdapUserDetailsManager(contextSource);
}
在应该处理密码更改的控制器中,我有以下代码:
private final UserDetailsManager userDetailsManager;
public AccountController(
@Qualifier("adUserDetailsManager") UserDetailsManager userDetailsManager) {
this.userDetailsManager = userDetailsManager;
}
@PostMapping("/account")
public ModelAndView changePassword(
ModelAndView modelAndView,
@RequestParam(required = true) String oldPassword,
@RequestParam(required = true) String newPassword,
@RequestParam(required = true) String confirmation) {
modelAndView.setViewName("account");
if (!StringUtils.equals(newPassword, confirmation)) {
throw new IllegalArgumentException("Passwords don't match");
}
userDetailsManager.changePassword(oldPassword, newPassword);
return modelAndView;
}
应用程序启动正常(没有依赖问题),但是一旦我运行该changePassword
方法,我就会得到一个异常,即无法访问 localhost 下的服务器:
localhost:389 [Root exception is java.net.ConnectException: Connection refused: connect]
似乎ContextSource
注入到我的getUserDetailsManager
方法中的是默认的指向 localhost,它不是来自我的 Active Directory 提供程序的实际 LDAP 连接。我在 ActiveDirectoryLdapAuthenticationProvider 上找不到任何可以给我一个实例UserDetailsManager
或至少为我提供ContextSource
AD 连接使用的东西的东西,所以我可以连接我自己的LdapUserDetailsManager
.
解决方案
- 您提供的是您自己的
AuthenticationManagerBuilder
,因此未正确配置上下文源。即,如果您使用的不是您自己的,则类似于
@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()
- 由于您使用的是自己的实现并且
contextSource
配置正确,因此您必须使用以下内容:
- 选项1:
@Bean("adUserDetailsManager")
public UserDetailsManager getUserDetailsManager() {
String providerUrl = "your ldap url here";
DefaultSpringSecurityContextSource contextSource
= new DefaultSpringSecurityContextSource(providerUrl);
contextSource.afterPropertiesSet();
return new LdapUserDetailsManager(contextSource);
}
- 选项 2:
@Bean
@Primary
public ContextSource contextSource() {
String providerUrl = "your ldap url here";
return new DefaultSpringSecurityContextSource(providerUrl);
}
@Bean("adUserDetailsManager")
public UserDetailsManager getUserDetailsManager(ContextSource contextSource) {
return new LdapUserDetailsManager(contextSource);
}
推荐阅读
- java - Java读取文件名并按升序存储
- python - 如何在熊猫的持续时间计算中排除周末和节假日
- python - 自定义数据结构:具有累积值的字典字典
- ruby-on-rails - Ruby、Rspec 和产量存根
- javascript - 什么函数返回另一个函数,其参数也声明为常量?
- google-apps-script - 将工作表保存为 PDF
- javascript - Javascript GooglMaps API 句柄不经常工作
- ios - 在 Xamarin iOS 中使用 FirebasePushNotificationPlugin 时没有有效的“aps 环境”
- angular - Angular HttpClient:从 RESTfull API 页面获取数据(下一页循环)
- javascript - 如何在启动应用程序时从表中加载 json 文件中的数据?