Для программного обеспечения, находящегося в активной разработке, мы используем Spring Boot (с Spring Security) и Keycloak Adapter.
Целью является:
- требовать действительную аутентификацию для всех конечных точек, кроме тех, которые помечены
@Public
(см. фрагмент кода) (это работает) - аутентификация должна быть через OAuth - клиент получает токен напрямую от Keycloak, а адаптер Spring Security + Keycloak проверяет его действительность.
- опционально также поддерживается базовая аутентификация (адаптер Keycloak можно настроить для выполнения входа в систему и сделать его похожим на обычную аутентификацию токена для остальной части кода) (это также работает)
Все работает нормально, но у меня проблемы с пониманием некоторых деталей:
KeycloakWebSecurityConfigurerAdapter
включаетCSRF
защиту. Я думаю, это сделано только для того, чтобы он мог зарегистрировать свой собственный Matcher, чтобы разрешать запросы от Keycloak- Он позволяет управлять сеансом и требует некоторых соответствующих bean-компонентов.
- Несмотря на то, что запросы выполняются с аутентификацией токена, возвращается
JSESSIONID
cookie.
По моему мнению:
- сеансы не должны быть необходимы, поскольку используется аутентификация по токену без сохранения состояния (так почему
KeycloakWebSecurityConfigurerAdapter
его включает). Это только для частиBASIC Auth
? - поскольку сеансы включены,
CSRF
защита действительно необходима, но я не хочу в первую очередь сеансов, и тогда API не будет нуждаться вCSRF
защите, верно? - даже если я устанавливаю
http.sessionManagement().disable()
после вызоваsuper.configure(http)
, устанавливаетсяJSESSIONID
cookie (так откуда это?)
Как указано в фрагменте кода, SessionAuthenticationStrategy
не устанавливается равным NULL один раз, поскольку мы используем 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();
}
}