Для программного обеспечения в активной разработке мы используем Spring Boot (с Spring Security) и адаптер Keycloak.
Цель:
- требуется действительная аутентификация для всех конечных точек, кроме отмеченных
@Public
(см. Фрагмент кода) (это работает)
- аутентификация должна быть через OAuth - клиент получает токен непосредственно от Keycloak, а адаптер Spring Security + Keycloak удостоверяется, что он действителен
- опционально, Basic Auth также поддерживается (адаптер Keycloak может быть настроен для выполнения входа в систему и отображения его как обычная авторизация токена для остальной части кода) (это также работает)
Все работает нормально, как есть, но у меня есть некоторые проблемы с пониманием некоторых деталей:
-
KeycloakWebSecurityConfigurerAdapter
обеспечивает защиту CSRF
. Я думаю, что это сделано только для того, чтобы он мог зарегистрировать свой собственный Matcher для разрешения запросов от Keycloak
- Включает управление сессиями и требует некоторых соответствующих компонентов
- Даже если запросы выполняются с помощью аутентификации токена,
JSESSIONID
cookie возвращается
Согласно моему пониманию:
- не требуются, так как используется аутентификация токена без сохранения состояния (так почему
KeycloakWebSecurityConfigurerAdapter
включает его). Это только для BASIC Auth
части?
- , поскольку сеансы включены, защита
CSRF
действительно необходима, но я не хочу, чтобы сеансы были в первую очередь, и тогда API не потребовалась бы защита CSRF
, верно?
- , даже если я установлю
http.sessionManagement().disable()
после вызова super.configure(http)
, будет установлен файл cookie JSESSIONID
(так откуда он?)
Как указано во фрагменте кода, SessionAuthenticationStrategy
не устанавливается равным нулю один раз, поскольку мы используем часть Authorization
Keycloak, а приложение - Service Account Manager
(таким образом, управляя этими записями ресурсов).
Было бы замечательно, если бы кто-то мог прояснить ситуацию. Заранее спасибо!
@KeycloakConfiguration
public class WebSecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
@Inject private RequestMappingHandlerMapping requestMappingHandlerMapping;
@Override
protected void configure(final HttpSecurity http) throws Exception {
super.configure(http);
http
.authorizeRequests()
.requestMatchers(new PublicHandlerMethodMatcher(requestMappingHandlerMapping))
.permitAll()
.anyRequest()
.authenticated();
}
// ~~~~~~~~~~ Keycloak ~~~~~~~~~~
@Override
@ConditionalOnMissingBean(HttpSessionManager.class)
@Bean protected HttpSessionManager httpSessionManager() {
return new HttpSessionManager();
}
/**
* {@link NullAuthenticatedSessionStrategy} is not used since we initiate logins
* from our application and this would not be possible with {@code bearer-only}
* clients (for which the null strategy is recommended).
*/
@Override
@Bean protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
/**
* HTTP session {@link ApplicationEvent} publisher needed for the
* {@link SessionRegistryImpl} of {@link #sessionAuthenticationStrategy()}
* to work properly.
*/
@Bean public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
@Override
@Bean public KeycloakAuthenticationProvider keycloakAuthenticationProvider() {
return super.keycloakAuthenticationProvider();
}
}