Grails - Аутентификация в Active Directory с использованием Spring Security - ошибка неверных учетных данных - PullRequest
0 голосов
/ 09 июля 2019

Я пытаюсь реализовать безопасность для REST API с помощью плагинов grails-sporing-security-rest и grails-spring-security-ldap.

Поток должен быть таким, как только поставщик аутентификации будет реализован, он аутентифицирует пользователя, используя механизм аутентификации.

но в моем случае я пытаюсь аутентифицировать запрос POST имени пользователя и пароля JSON, и ниже вывод.

если вы наблюдаете журнал, аутентификация SpringSecurityLDAPTemplate прошла успешно, но когда запрос переходит к следующему фильтру RestAuthenticationFilter, он сообщает об ошибке Bad Credentials. Это вносит некоторую путаницу. / Api / login - это конечная точка безопасности Spring, которая при успешной аутентификации примет имя пользователя и пароль, должна вернуть соответствующий токен, но почему он снова отправляется в RestAuthenticationFilter?

С правильным именем пользователя и паролем:

o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/api/login'; against '/api/**'
o.s.security.web.FilterChainProxy        : /api/login at position 1 of 7 in additional filter chain; firing Filter: 'SecurityRequestHolderFilter'
o.s.security.web.FilterChainProxy        : /api/login at position 2 of 7 in additional filter chain; firing Filter: 'MutableLogoutFilter'
o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/api/login'; against '/logoff'
o.s.security.web.FilterChainProxy        : /api/login at position 3 of 7 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
g.p.s.rest.RestAuthenticationFilter      : Actual URI is /api/login; endpoint URL is /api/login
g.p.s.rest.RestAuthenticationFilter      : Applying authentication filter to this request
c.DefaultJsonPayloadCredentialsExtractor : Extracted credentials from JSON payload. Username: xxxxxxx, password: [PROTECTED]
g.p.s.rest.RestAuthenticationFilter      : Trying to authenticate the request
o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider
o.s.s.ldap.SpringSecurityLdapTemplate    : Searching for entry under DN '', base = 'dc=xxx,dc=xxx,dc=xxx,dc=xxx', filter = '(&(objectClass=user)(userPrincipalName={0}))'
 g.p.s.rest.RestAuthenticationFilter      : Authentication failed: Bad credentials
g.p.s.r.token.bearer.BearerTokenReader   : Looking for bearer token in Authorization header, query string or Form-Encoded body parameter
g.p.s.r.token.bearer.BearerTokenReader   : No token found
g.p.s.r.token.bearer.BearerTokenReader   : Token: null
.BearerTokenAuthenticationFailureHandler : Sending status code 401 and header WWW-Authenticate: Bearer

с неправильным именем пользователя и паролем:

o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider
ctiveDirectoryLdapAuthenticationProvider : Active Directory authentication failed: Supplied password was invalid
 g.p.s.rest.RestAuthenticationFilter      : Authentication failed: Bad credentials

Resources.Groovy

import myapp.MyUserDetailsContextMapper
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider

// Place your Spring DSL code here
beans = {
    ldapAuthProvider1(ActiveDirectoryLdapAuthenticationProvider, "xxx" ,"xxxx" ) {
        userDetailsContextMapper = ldapUserDetailsMapper
    }
    ldapUserDetailsMapper(MyUserDetailsContextMapper) {

    }
}

application.groovy

grails.plugin.springsecurity.filterChain.chainMap = [
        //Stateless chain
        [
                pattern: '/api/**',
                filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter'
        ],

        //Traditional, stateful chain
        [
                pattern: '/stateful/**',
                filters: 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter'
        ]
]
grails.plugin.springsecurity.rest.token.storage.jwt.secret="xyz1234dsgsd4546dfhg345745754785756856856785679fghfgj"
grails.plugin.springsecurity.rest.login.active=true
grails.plugin.springsecurity.rest.login.endpointUrl="/api/login"
grails.plugin.springsecurity.rest.login.failureStatusCode=401

application.yml - конфигурации grails

grails:
    plugin:
        springsecurity:
            providerNames: ["ldapAuthProvider1","anonymousAuthenticationProvider"]
            useSecurityEventListener: true
            ldap:
                search:
                    attributesToReturn: ['mail', 'displayName']
                    filter: '(sAMAccountName={0})'
                    searchSubtree: true
                authorities:
                    retrieveDatabaseRoles:  false
                    ignorePartialResultException: true
                authenticator:
                    useBind: true
                    attributesToReturn: null
                auth:
                    useAuthPassword: true
            rest:
                login:
                    useJsonCredentials: true
                    usernamePropertyName: username
                    passwordPropertyName: password

UPDATE:

Устранена проблема, и заметил это.

под строкой кода находится в SpringSecurityLdapTemplate класс и метод searchForSingleEntryInternal - из релиза spring-security-ldap 4.2.3. Который вызывается из ActiveDirectoryLdapAuthenticationProvider класса для извлечения информации из LDAP.

final DistinguishedName searchBaseDn = new DistinguishedName(base);
    final NamingEnumeration<SearchResult> resultsEnum = ctx.search(searchBaseDn,
            filter, params, buildControls(searchControls));

    if (logger.isDebugEnabled()) {
        logger.debug("Searching for entry under DN '" + ctxBaseDn + "', base = '"
                + searchBaseDn + "', filter = '" + filter + "'");
    }

    Set<DirContextOperations> results = new HashSet<DirContextOperations>();
    try {
        while (resultsEnum.hasMore()) {
            SearchResult searchResult = resultsEnum.next();
            DirContextAdapter dca = (DirContextAdapter) searchResult.getObject();
            Assert.notNull(dca,
                    "No object returned by search, DirContext is not correctly configured");

В этом случае searchResult.getObject возвращает значение null, которое вызывает сбой аутентификации, но я убедился, что могу получить атрибуты из resultsEnum.

Любая помощь очень ценится. Спасибо.

1 Ответ

0 голосов
/ 16 июля 2019

Эта строка кода, которая является частью класса ActiveDirectoryAuthenticationProvider, создает проблему, поскольку она ожидает, что объект LdapContext повлияет на его передачу как ноль. Расширенный AbstractAuthenticationProvider и созданный пользовательский обработчик аутентификации для решения проблемы.

DirContextAdapter dca = (DirContextAdapter) searchResult.getObject();
...