Spring 安全活动目录 LDAP 身份验证错误
Spring Security Active directory LDAP Authentication error
当我使用 Spring Security Active directory LDAP 身份验证时,我收到一条错误消息,显示 PartialResultException 用户已通过身份验证。我还创建了一个测试运行程序文件,它可以在其中对用户进行身份验证而不会出现错误,但是当我对活动目录进行身份验证时,我无法进行身份验证。感谢您的宝贵帮助。
测试Runner2.java文件
package com.company.test;
import java.util.Hashtable;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
public class Runner2 {
private static String providerUrl = "ldap://ADHO.COMPANY.NET:389";
private static String principle = "@company.ad";
public static final String SEARCH_BY_SAM_ACCOUNT_NAME = "(sAMAccountName=%s)";
public static boolean authenticateAD(String user , String password) throws Exception {
InitialDirContext context=null;
Hashtable<String, String> env = new Hashtable<String, String>();
String securityPrinciple = user + principle;
System.out.println("Security principal to search ->"+securityPrinciple);
// Configure our directory context environment.
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, providerUrl);
env.put(Context.SECURITY_PRINCIPAL, securityPrinciple);
env.put(Context.SECURITY_CREDENTIALS, password);
try {
context = new InitialDirContext(env);
return true;
}catch(AuthenticationException e) {
throw new AuthenticationException();
}catch(Exception e) {
throw new Exception();
}
finally {
try {
if (context != null) {
context.close();
}
} catch (NamingException e) {
}
}
}
public static void main(String[] args) throws Exception {
String r1 = "USRXXXX;
String r2 = "Pass#word102";
authenticateAD(r1,r2);
}
}
ldap.properties 文件
ad.domain=company.ad
ad.url=ldap://ADHO.COMPANY.NET:389/
SpringSecurityConfig.java 文件
package com.company.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
import com.onezero.config.AuthenticationEntryPoint;
import java.util.Arrays;
@Configuration
@EnableWebSecurity
@PropertySource("classpath:ldap.properties")
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private Environment env;
@Bean
public AuthenticationEntryPoint customAuthenticationEntry() throws Exception {
return new AuthenticationEntryPoint();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/welcome","/atm/**","/atm2/**","/**","/survey/**","/usrauth/**").authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(customAuthenticationEntry())
.and()
.exceptionHandling()
.and()
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
}
@Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
env.getProperty("ad.domain"), env.getProperty("ad.url"));
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
return provider;
}
}
A PartialResultException
可以在服务器 returns 引用时抛出。那是服务器的说法 "I don't know what you're talking about, but I know who does." 在 this answer 中对选项有很好的解释。一是设置:
env.put(Context.REFERRAL, "follow");
这将告诉它将请求发送到服务器告诉我们去的任何地方。但我认为这不是一个好的解决方案。当只有一个请求时,您最终将发出两个网络请求。更改您的配置以指向正确的位置是更好的选择。
找出它在抱怨什么的一种方法是检查 PartialResultException
对象的 resolvedName
属性。这应该会告诉您它将发送给您的位置,并且您可以更改您的配置以首先指向那里。
我不是 Java 开发人员,所以这些都是猜测,但我确实知道 AD 的工作原理。无论如何都试一试。
当我使用 Spring Security Active directory LDAP 身份验证时,我收到一条错误消息,显示 PartialResultException 用户已通过身份验证。我还创建了一个测试运行程序文件,它可以在其中对用户进行身份验证而不会出现错误,但是当我对活动目录进行身份验证时,我无法进行身份验证。感谢您的宝贵帮助。
测试Runner2.java文件
package com.company.test;
import java.util.Hashtable;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
public class Runner2 {
private static String providerUrl = "ldap://ADHO.COMPANY.NET:389";
private static String principle = "@company.ad";
public static final String SEARCH_BY_SAM_ACCOUNT_NAME = "(sAMAccountName=%s)";
public static boolean authenticateAD(String user , String password) throws Exception {
InitialDirContext context=null;
Hashtable<String, String> env = new Hashtable<String, String>();
String securityPrinciple = user + principle;
System.out.println("Security principal to search ->"+securityPrinciple);
// Configure our directory context environment.
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, providerUrl);
env.put(Context.SECURITY_PRINCIPAL, securityPrinciple);
env.put(Context.SECURITY_CREDENTIALS, password);
try {
context = new InitialDirContext(env);
return true;
}catch(AuthenticationException e) {
throw new AuthenticationException();
}catch(Exception e) {
throw new Exception();
}
finally {
try {
if (context != null) {
context.close();
}
} catch (NamingException e) {
}
}
}
public static void main(String[] args) throws Exception {
String r1 = "USRXXXX;
String r2 = "Pass#word102";
authenticateAD(r1,r2);
}
}
ldap.properties 文件
ad.domain=company.ad
ad.url=ldap://ADHO.COMPANY.NET:389/
SpringSecurityConfig.java 文件
package com.company.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
import com.onezero.config.AuthenticationEntryPoint;
import java.util.Arrays;
@Configuration
@EnableWebSecurity
@PropertySource("classpath:ldap.properties")
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private Environment env;
@Bean
public AuthenticationEntryPoint customAuthenticationEntry() throws Exception {
return new AuthenticationEntryPoint();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/welcome","/atm/**","/atm2/**","/**","/survey/**","/usrauth/**").authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(customAuthenticationEntry())
.and()
.exceptionHandling()
.and()
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
}
@Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
env.getProperty("ad.domain"), env.getProperty("ad.url"));
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
return provider;
}
}
A PartialResultException
可以在服务器 returns 引用时抛出。那是服务器的说法 "I don't know what you're talking about, but I know who does." 在 this answer 中对选项有很好的解释。一是设置:
env.put(Context.REFERRAL, "follow");
这将告诉它将请求发送到服务器告诉我们去的任何地方。但我认为这不是一个好的解决方案。当只有一个请求时,您最终将发出两个网络请求。更改您的配置以指向正确的位置是更好的选择。
找出它在抱怨什么的一种方法是检查 PartialResultException
对象的 resolvedName
属性。这应该会告诉您它将发送给您的位置,并且您可以更改您的配置以首先指向那里。
我不是 Java 开发人员,所以这些都是猜测,但我确实知道 AD 的工作原理。无论如何都试一试。