Spring boot 2 + аутентификация Microsoft AD + атрибут userPassword не найден - PullRequest
0 голосов
/ 04 ноября 2019

Я пытаюсь аутентифицировать пользователя по Microsoft AD, используя весеннюю загрузку 2.1.9.RELEASE. Я могу найти пользователя dn из AD, но он не аутентифицирует пользователя и не получает исключение нулевого указателя.

Мой код WebSecurityConfig

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        // auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());

        auth.ldapAuthentication().userDnPatterns("CN={0},OU=Users")
                .groupSearchBase("ou=groups")
                .userSearchFilter("(sAMAccountName={0})").contextSource()
                .url(AD_URL)
                .managerDn(AD_USERNAME).managerPassword(AD_PASSWORD).and()
                .passwordCompare()
                .passwordEncoder(new LdapShaPasswordEncoder())
                .passwordAttribute("userPassword");

    }

ОШИБКА LOG

w.a.UsernamePasswordAuthenticationFilter : Request is to process authentication
o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider
o.s.s.l.a.LdapAuthenticationProvider     : Processing authentication request for user: <username>
o.s.l.c.support.AbstractContextSource    : Got Ldap context on server 'ldap://<companyname>.com:389/dc=<companyname>,dc=com'
o.s.s.l.s.FilterBasedLdapUserSearch      : Searching for user '<username>', with user search [ searchFilter: '(sAMAccountName={0})', searchBase: '', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
o.s.l.c.support.AbstractContextSource    : Got Ldap context on server 'ldap://<companyname>.com:389/dc=<companyname>,dc=com'
o.s.s.ldap.SpringSecurityLdapTemplate    : Searching for entry under DN 'dc=<companyname>,dc=com', base = '', filter = '(sAMAccountName={0})'
o.s.s.ldap.SpringSecurityLdapTemplate    : Found DN: CN=<User Full Name>,OU=Users,OU=HM Bangalore,OU=Office Locations
o.s.s.ldap.SpringSecurityLdapTemplate    : Ignoring PartialResultException
.s.s.l.a.PasswordComparisonAuthenticator : Performing LDAP compare of password attribute 'userPassword' for user 'CN=<User Full Name>,OU=Users,OU=HM Bangalore,OU=Office Locations'
o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@456cde20
w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/api] threw exception

java.lang.NullPointerException: null
    at org.springframework.security.crypto.password.LdapShaPasswordEncoder.extractPrefix(LdapShaPasswordEncoder.java:193) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.crypto.password.LdapShaPasswordEncoder.matches(LdapShaPasswordEncoder.java:162) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.crypto.password.LdapShaPasswordEncoder.matches(LdapShaPasswordEncoder.java:158) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator.isPasswordAttrCompare(PasswordComparisonAuthenticator.java:121) ~[spring-security-ldap-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator.authenticate(PasswordComparisonAuthenticator.java:109) ~[spring-security-ldap-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:187) ~[spring-security-ldap-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:85) ~[spring-security-ldap-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:175) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:200) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
.
.
.

При дальнейшем изучении журнала ошибок я обнаружил, что приведенный ниже код пытается получить зашифрованный пароль от объекта пользователя, но моего пароляAttributeName "userPassword" нет в объекте пользователя

org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator.isPasswordAttrCompare (PasswordComparisonAuthenticator.java:121)

.
.
.
    private boolean isPasswordAttrCompare(DirContextOperations user, String password) {
        String passwordAttrValue = getPassword(user);
        return passwordEncoder.matches(password, passwordAttrValue);
    }

    private String getPassword(DirContextOperations user) {
        Object passwordAttrValue = user.getObjectAttribute(this.passwordAttributeName);
        if (passwordAttrValue == null) {
            return null;
        }
        if (passwordAttrValue instanceof byte[]) {
            return new String((byte[]) passwordAttrValue);
        }
        return String.valueOf(passwordAttrValue);
    }
.
.
.

Не уверен, почему я не могу получить зашифрованный пароль из AD. Любая помощь будет высоко ценится.

1 Ответ

1 голос
/ 04 ноября 2019

Microsoft Active Directory не использует обычный пароль "userPassword", а скорее " unicodePwd ".

Кроме того, как и во многих реализациях сервера LDAP, Microsoft Active Directory будетnot возвращает значение для атрибута пароля.

Наконец, выполнение сравнения LDAP по паролю является плохой практикой, и не следует использовать в качестве некоторых встроенных функций, таких какИстечение срока действия пароля и обнаружение нарушителя могут быть обойдены при выполнении запроса сравнения для атрибута userPassword. Вы всегда должны выполнять операцию связывания с LDAP.

...