Spring Boot Microsoft AD身份验证

时间:2018-11-20 09:34:31

标签: java spring-boot spring-security active-directory

我对Spring Boot知之甚少,甚至对Active Directory也不甚了解。

我需要使用Spring Boot和JWT针对Microsoft Active Directory进行身份验证。我已经与内存中的用户一起使用JWT,但是我无法对来自Microsoft AD的用户进行身份验证。

Microsoft AD设置:

Spring Boot应用运行于:192.168.1.31:8082
Spring Boot配置:

import com.mts.oh.config.cors.SimpleCORSFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.Arrays;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SimpleCORSFilter myCorsFilter;

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(myCorsFilter, ChannelProcessingFilter.class).
                csrf().disable().
                exceptionHandling().authenticationEntryPoint(unauthorizedHandler).
                and().
                authorizeRequests().
                antMatchers(HttpMethod.POST, "/api/login").permitAll().
                anyRequest().authenticated().
                and().
                addFilterBefore(new LoginInterceptor("/api/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class).
                addFilterBefore(new JwtInterceptor(), UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        authManagerBuilder.authenticationProvider(activeDirectoryLdapAuthenticationProvider()).userDetailsService(userDetailsService());
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
    }

    @Bean
    public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider("bmad.com",
            "ldap://192.168.1.166:389/DC=bmad,DC=com");
    provider.setSearchFilter("OU=devs,OU=employees");
    provider.setConvertSubErrorCodesToExceptions(true);
    provider.setUseAuthenticationRequestCredentials(true);

        return provider;
    }
}

登录端点为:/ api / login。 邮递员要求:

堆栈跟踪:

> rg.springframework.security.authentication.BadCredentialsException:
> Bad credentials
>       at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.badCredentials(ActiveDirectoryLdapAuthenticationProvider.java:295)
>       at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.badCredentials(ActiveDirectoryLdapAuthenticationProvider.java:300)
>       at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.raiseExceptionForErrorCode(ActiveDirectoryLdapAuthenticationProvider.java:267)
>       at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.handleBindException(ActiveDirectoryLdapAuthenticationProvider.java:233)
>       at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.bindAsUser(ActiveDirectoryLdapAuthenticationProvider.java:208)
>       at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.doAuthentication(ActiveDirectoryLdapAuthenticationProvider.java:144)
>       at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:85)
>       at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
>       at com.mts.oh.config.security.LoginInterceptor.attemptAuthentication(LoginInterceptor.java:28)
>       at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
>       at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
>       at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
>       at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
>       at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
>       at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
>       at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
>       at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
>       at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
>       at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
>       at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
>       at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
>       at com.mts.oh.config.cors.SimpleCORSFilter.doFilter(SimpleCORSFilter.java:32)
>       at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
>       at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
>       at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
>       at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
>       at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
>       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
>       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
>       at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
>       at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
>       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
>       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
>       at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108)
>       at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
>       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
>       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
>       at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
>       at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
>       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
>       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
>       at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
>       at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
>       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
>       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
>       at com.mts.oh.config.cors.SimpleCORSFilter.doFilter(SimpleCORSFilter.java:32)
>       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
>       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
>       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
>       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
>       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
>       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
>       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
>       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
>       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
>       at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
>       at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
>       at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
>       at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457)
>       at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
>       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
>       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
>       at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
>       at java.lang.Thread.run(Thread.java:748)
>     Caused by: org.springframework.security.ldap.authentication.ad.ActiveDirectoryAuthenticationException:
> [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903C5, comment:
> AcceptSecurityContext error, data 773, v2580 ]
>       at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.raiseExceptionForErrorCode(ActiveDirectoryLdapAuthenticationProvider.java:250)
>       ... 61 common frames omitted
>     Caused by: javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903C5, comment: AcceptSecurityContext
> error, data 773, v2580 ]
>       at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3154)
>       at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3100)
>       at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2886)
>       at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2800)
>       at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:319)
>       at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)
>       at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
>       at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
>       at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
>       at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
>       at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
>       at javax.naming.InitialContext.init(InitialContext.java:244)
>       at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:154)
>       at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider$ContextFactory.createContext(ActiveDirectoryLdapAuthenticationProvider.java:402)
>       at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.bindAsUser(ActiveDirectoryLdapAuthenticationProvider.java:203)
>       ... 59 common frames omitted

我尝试了用户名和密码的不同组合,但都不起作用:

  • John Doe / ****
  • johnupn / ****
  • johnupn@bmad.com / ****
  • bmad \ johnupn / ****

我从以下位置获取了Spring Boot配置:
https://medium.com/@dmarko484/spring-boot-active-directory-authentication-5ea04969f220

https://www.ziaconsulting.com/developer-help/spring-security-active-directory/
但是这些对我不起作用。

1 个答案:

答案 0 :(得分:0)

从登录域的计算机上,用户可以使用whoami查找其帐户的值。下面显示了分别获取用户的sAMAccountName,userPrincipalName和标准专有名称的命令。通过LDAP进行身份验证时,Active Directory将所有这三个名称用作用户名。

c:>whoami
mydomain\lisa

c:>whoami /upn
lisa@mydomain.ccTLD

c:>whoami /fqdn
CN=Smith\, Lisa,OU=GPOTest,OU=IT,OU=Company,DC=mydomain,DC=ccTLD