Я пишу сервис аутентификации в нашей сервисной архитектуре, которая будет в основном реализацией Spring OAuth2 Authorization Server.Исходя из этого, мне нужно будет аутентифицировать предоставленные учетные данные по множеству различных источников для поддержки устаревшей среды.
Я в основном сконцентрирован на использовании потока учетных данных клиента, где пользователи (другие службы) будут использовать свои собственные учетные данные для получения токенаи на данный момент не потребуется авторизация или обновление OAuth2.
Я успешно смог запустить приложение Spring Boot, защищенное Spring Security (@EnableWebSecurity
).Я также успешно настроил Сервер авторизации (@EnableAuthorizationServer
), который предоставляет необходимые конечные точки (/oauth/token
) для предоставления токена.Я был в состоянии настроить Сервер авторизации с помощью памяти и пользовательского ClientDetailsService для успешного получения токена.Это все лишь для того, чтобы продемонстрировать себе, что я могу заставить что-то работать.
Моя проблема в том, что мне нужно аутентифицировать учетные данные на основе собственного источника.У меня нет прямого доступа к паролям и, конечно, я не знаю, как они кодируются.
После копания в коде Spring я мог видеть, что через DaoAuthenticationProvider
он выполняет аутентификацию, вызывая PasswordEncoder.matches()
,К сожалению, я не получаю пароль от ClientDetailsService
, и при этом я не знаю, как пароль закодирован, если я это сделал, поэтому пользовательский PasswordEncoder
не очень мне помогает (также мне нужно было бы сопоставить несколькими способами только содин PasswordEncoder
).Итак, у меня осталось определение собственного AuthenticationProvider
(или AuthenticationManager
).
Я смог реализовать свой собственный AuthenticationProvider
и предоставить его для конфигурации Spring Security.Это сработало отлично, и я смог перенести аутентификацию на моего собственного провайдера, который может делать все, что я сочту нужным (например, делегировать другой сервис для аутентификации), но это работало только для конечных точек не OAuth2.
Теперь здесь все начинает разваливаться.По какой-то причине я не могу заставить конечную точку /oauth/token
использовать определенные AuthenticationManager
или AuthenticationProvider
s, которые я предоставляю.По умолчанию он всегда равен AuthenticationManger
с AnonymousAuthenticationProvider
и DaoAuthenticationProvider
.
WebSecurity
Не очень интересно здесь.Я выставляю менеджер аутентификации глобально в попытке зарегистрировать его в конфигурации OAuth2.Я оставил в некотором закомментированном коде, чтобы показать некоторые другие вещи, которые я пробовал, но все они в значительной степени выполняют одно и то же: он работает со всем, кроме конечных точек OAuth2.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public AuthenticationProvider customAuthenticationProvider;
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
// return new ProviderManager(Arrays.asList(customAuthenticationProvider));
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(customAuthenticationProvider);
}
// @Autowired
// public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth.authenticationProvider(customAuthenticationProvider);
// }
}
AuthServer
Я сократил это до того, что, как я считаю, должно быть правильной конфигурацией.Я намеренно пропустил ClientDetailsService
, так как это часть конфигурации провайдера, и она работает правильно.Я игнорирую TokenStore
и использую значения по умолчанию, пока не смогу получить аутентификацию.Опять же, authenticationManager
здесь должно быть глобальным, предоставляемым WebSecurity.Я также попытался создать новый ProviderManager
в конфигураторе конечных точек, но у меня это тоже не сработало.
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()")
;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
Я также безуспешно пытался расширить AuthorizationServerSecurityConfiguration
:
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig2 extends AuthorizationServerSecurityConfiguration {
@Autowired
public AuthenticationProvider customAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
}
Я бы ожидал, что мой пользовательский AuthenticationProvider
будет отображаться в списке, но он не будет отображаться со всем, что я пробовал.
Это может быть преднамеренным, но если это так, топравильный способ предоставления пользовательских схем аутентификации?
Я бы действительно хотел этого избежать, но действительно ли я должен реализовать собственный фильтр и обойти все приятные вещи, которые предоставляет Spring?Если да, как бы я поступил так?