对于正在积极开发的软件,我们使用 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(所以这是从哪里来的?)
如代码片段中所述,由于我们使用Keycloak 的一部分并且应用程序是一个(因此管理这些资源记录) ,SessionAuthenticationStrategy
因此不会将其设置为 null 一次。Authorization
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();
}
}