Spring Custom AuthenticationProvider для принципала с дополнительными данными

1

Я новичок в Spring.

Моя цель состоит в том, чтобы иметь некоторый AuthenticationProvider с настраиваемым методом authenticate который принимает объект Authenticate как аргумент с более чем просто именем пользователя и паролем. Позвольте сказать имя области (и могут быть 2 пользователя с тем же именем пользователя, когда они находятся в разных сферах). Я уже искал ответы на свой вопрос, но простые ответы на вопросы об аутентификации объясняют, как расширить AbstractUserDetailsAuthenticationProvider, который не удовлетворяет мои потребности, потому что метод retrieve принимает имя пользователя как аргумент, в то время как мне также требуется имя области для извлечения пользователя. Сложные из них касаются расширения или реализации всех видов различных классов и интерфейсов Spring без объяснения контекста.

Итак, простой вопрос:

Как мне реализовать/расширить AuthenticationProvider, чтобы читать пользовательские данные из объекта Authentication?

Мой вызов будет выглядеть так (да, я хочу получить токен OAuth2):

curl -vX POST http://localhost:9001/oauth/token \
-d "client_id=myId&client_secret=secret&grant_type=password&username=myUser&password=1234&realm=realm3"

Обратите внимание на realm=realm3 в конце.

Вызов без дополнительных данных и с моим собственным подклассом AbstractUserDetailsAuthenticationProvider уже работает, когда существует только одна область.

Заранее спасибо!

Теги:
spring-security
spring
spring-security-oauth2

1 ответ

1
Лучший ответ

Как мне реализовать/расширить AuthenticationProvider, чтобы читать пользовательские данные из объекта Authentication?

RealmAuthenticationProvider

public class RealmAuthenticationProvider implements AuthenticationProvider {

    private RUPAuthenticator rupAuthenticator;

    public RealmAuthenticationProvider(RUPAuthenticator rupAuthenticator) {
        this.rupAuthenticator = rupAuthenticator;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        Object principal = authentication.getPrincipal();
        Object credentials = authentication.getCredentials();
        Object realm = authentication.getDetails();
        if (rupAuthenticator.authenticate(principal, credentials, realm)) {
            List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
            grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER")); //use any GrantedAuthorities you need
            return new RealmAuthenticationToken(principal, credentials, realm, grantedAuths);
        };
        return null;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return RealmAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

RealmAuthenticationToken

public class RealmAuthenticationToken extends UsernamePasswordAuthenticationToken {

    private Object realm;

    public RealmAuthenticationToken(Object principal, Object credentials, Object realm, Collection<? extends GrantedAuthority> authorities) {
        super(principal,credentials, authorities);
        this.realm = realm;
    }
}

RUPAuthenticator

public interface RUPAuthenticator {
    boolean authenticate(Object username, Object password, Object realm);
}

Вам просто нужно предоставить реализацию для RUPAuthenticator, в которой указано, правильны ли имя пользователя, пароль, комбинации областей.

Затем зарегистрируйте пользовательский AuthenticationProvider (RealmAuthenticationProvider) в качестве компонента. Ниже приведен пример поставщика проверки подлинности, который принимает запросы от конкретного пользователя:

@Bean
public AuthenticationManager authenticationManager() {
        List<AuthenticationProvider> providers = new ArrayList<AuthenticationProvider>();
        providers.add(new RealmAuthenticationProvider(new RUPAuthenticator() {
            @Override
            public boolean authenticate(Object username, Object password, Object realm) {
                return (username.equals("sa") && password.equals("sa") && realm.equals("realm2"));
            }
        }));
        return new ProviderManager(providers);
    }

Надеюсь, это то, что вы искали.

  • 0
    Большое спасибо! Это выглядит очень многообещающе, я уже отмечу его как ответ, хотя мне все еще нужно выяснить, как классы связаны друг с другом, последовательность вызовов и что нужно изменить в файле security.xml, чтобы это сработало.
  • 0
    Я еще не смог интегрировать это. Разве мне не нужно упоминать UserDetailsService для <authentication-manager> в security.xml? И UserDetailsService имеет loadUserByUsername (String username) и предполагает, что имя пользователя уникально.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню