spring 具有 Keycloak 安全性的引导执行器端点
spring boot actuator endpoints with Keycloak security
我们有一个带有执行器端点的 spring 引导项目 (2.3.0.RELEASE),我们正在使用 KeycloakWebSecurityConfigurerAdapter 将 keycloak 引入到项目中,我如何防止执行器端点被 keycloak 过滤器链保护.
我们希望通过基本身份验证保护“/actuator/**”端点。
目前我们有一个带有@Order(1) 的自定义WebSecurityConfigurerAdapter,我们将基本身份验证应用于“/actuator/**”,然后我们有@Order(2) antotated KeycloakWebSecurityConfigurerAdapter
因此注册了 2 个过滤器链,当我调用执行器端点时,第二个过滤器链因未授权 401 而失败
是否可以阻止处理第二个过滤器链上的“/actuator/**”资源路径?
第一个执行器安全配置。
@Configuration
@Order(1)
public class ActuatorWebSecurityConfig extends WebSecurityConfigurerAdapter {
private final String username;
private final String password;
private final PasswordEncoder encoder;
public ActuatorWebSecurityConfig(
@Value("${spring.security.user.name}") String username,
@Value("${spring.security.user.password}") String password,
Optional<PasswordEncoder> encoder) {
this.username = username;
this.password = password;
this.encoder = encoder.orElseGet(PasswordEncoderFactories::createDelegatingPasswordEncoder);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(username)
.password(encoder.encode(password))
.roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.antMatcher("/actuator/**")
.authorizeRequests(authorize -> authorize.anyRequest().authenticated())
.httpBasic(Customizer.withDefaults());
}
}
第二个 keycloak 安全配置
@Order(2)
@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
private final String swaggerUrl;
private final CorsFilter corsFilter;
private final CustomSecurityConfig customSecurityConfig;
@Autowired
public SecurityConfig(
@Value("${springdoc.swagger-ui.url:#{null}}") String swaggerUrl,
CorsFilter corsFilter,
CustomSecurityConfig customSecurityConfig) {
this.swaggerUrl = swaggerUrl;
this.corsFilter = corsFilter;
this.customSecurityConfig = customSecurityConfig;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakProvider = keycloakAuthenticationProvider();
keycloakProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakProvider);
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new NullAuthenticatedSessionStrategy();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.csrf().disable()
.requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/actuator/**")));
.headers().frameOptions().disable()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/public/**", "/resources/**", "/resources/public/**").permitAll()
.antMatchers(OPTIONS, "/**").permitAll();
.authorizeRequests()
.antMatchers("/**")
.authenticated();
}
}
我已经尝试使用 keycloak 配置
.antMatchers("/actuator/**").permitAll();
并与
http.requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/actuator/**")));
但没有任何效果我收到执行器未经授权的 401
已注册的过滤器链:
2022-01-18 17:38:44,688 INFO org.springframework.security.web.DefaultSecurityFilterChain [main] Creating filter chain: Ant [pattern='/actuator/**'], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@25c6a9de, org.springframework.security.web.context.SecurityContextPersistenceFilter@56f3f9da, org.springframework.security.web.header.HeaderWriterFilter@33dcbdc2, org.springframework.security.web.csrf.CsrfFilter@522fdf0c, org.springframework.security.web.authentication.logout.LogoutFilter@365ad794, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@23df16cf, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@227cba85, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@b38dc7d, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@142422a4, org.springframework.security.web.session.SessionManagementFilter@2f0b7b6d, org.springframework.security.web.access.ExceptionTranslationFilter@74bca236, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@30587737]
2022-01-18 17:38:44,691 INFO org.springframework.security.web.DefaultSecurityFilterChain [main] Creating filter chain: NegatedRequestMatcher [requestMatcher=Ant [pattern='/actuator/**']], [com.betex.auth.filters.CorsFilter@20a9f5fb, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@10e28d97, org.springframework.security.web.context.SecurityContextPersistenceFilter@c6b08a5, org.springframework.security.web.header.HeaderWriterFilter@5f05cd7e, org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter@2a54c92e, org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter@55b62db8, org.springframework.security.web.authentication.logout.LogoutFilter@274f51ad, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@54980154, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@25874884, org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter@8cb7185, org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter@4dac40b, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@37d43b9b, org.springframework.security.web.session.SessionManagementFilter@11e8e183, org.springframework.security.web.access.ExceptionTranslationFilter@56f1db5f, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@78543f0d]
当您扩展 KeycloakWebSecurityConfigurerAdapter
时,适配器会注册一个 KeycloakAuthenticationProcessingFilter
类型的 Bean。这个filter是在SpringSecurity的SecurityFilterChain
注册的,因为是Bean,所以在原链中SpringBoot也会自动注册,所以即使SpringSecurity不应用它,稍后将在原始过滤器链中应用它。
尝试禁止此过滤器被 Spring Boot 注册,像这样:
@Bean
public FilterRegistrationBean registration(KeycloakAuthenticationProcessingFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
此外,如果您使用的是 OAuth 2,您可以考虑使用 spring-security-oauth2-resource-server
并简化资源服务器的配置。看看 documentation。这样您就不需要扩展自定义适配器,只需依赖 Spring Security.
的开箱即用配置
我们有一个带有执行器端点的 spring 引导项目 (2.3.0.RELEASE),我们正在使用 KeycloakWebSecurityConfigurerAdapter 将 keycloak 引入到项目中,我如何防止执行器端点被 keycloak 过滤器链保护.
我们希望通过基本身份验证保护“/actuator/**”端点。
目前我们有一个带有@Order(1) 的自定义WebSecurityConfigurerAdapter,我们将基本身份验证应用于“/actuator/**”,然后我们有@Order(2) antotated KeycloakWebSecurityConfigurerAdapter
因此注册了 2 个过滤器链,当我调用执行器端点时,第二个过滤器链因未授权 401 而失败
是否可以阻止处理第二个过滤器链上的“/actuator/**”资源路径?
第一个执行器安全配置。
@Configuration
@Order(1)
public class ActuatorWebSecurityConfig extends WebSecurityConfigurerAdapter {
private final String username;
private final String password;
private final PasswordEncoder encoder;
public ActuatorWebSecurityConfig(
@Value("${spring.security.user.name}") String username,
@Value("${spring.security.user.password}") String password,
Optional<PasswordEncoder> encoder) {
this.username = username;
this.password = password;
this.encoder = encoder.orElseGet(PasswordEncoderFactories::createDelegatingPasswordEncoder);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(username)
.password(encoder.encode(password))
.roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.antMatcher("/actuator/**")
.authorizeRequests(authorize -> authorize.anyRequest().authenticated())
.httpBasic(Customizer.withDefaults());
}
}
第二个 keycloak 安全配置
@Order(2)
@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
private final String swaggerUrl;
private final CorsFilter corsFilter;
private final CustomSecurityConfig customSecurityConfig;
@Autowired
public SecurityConfig(
@Value("${springdoc.swagger-ui.url:#{null}}") String swaggerUrl,
CorsFilter corsFilter,
CustomSecurityConfig customSecurityConfig) {
this.swaggerUrl = swaggerUrl;
this.corsFilter = corsFilter;
this.customSecurityConfig = customSecurityConfig;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakProvider = keycloakAuthenticationProvider();
keycloakProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakProvider);
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new NullAuthenticatedSessionStrategy();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.csrf().disable()
.requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/actuator/**")));
.headers().frameOptions().disable()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/public/**", "/resources/**", "/resources/public/**").permitAll()
.antMatchers(OPTIONS, "/**").permitAll();
.authorizeRequests()
.antMatchers("/**")
.authenticated();
}
}
我已经尝试使用 keycloak 配置
.antMatchers("/actuator/**").permitAll();
并与
http.requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/actuator/**")));
但没有任何效果我收到执行器未经授权的 401
已注册的过滤器链:
2022-01-18 17:38:44,688 INFO org.springframework.security.web.DefaultSecurityFilterChain [main] Creating filter chain: Ant [pattern='/actuator/**'], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@25c6a9de, org.springframework.security.web.context.SecurityContextPersistenceFilter@56f3f9da, org.springframework.security.web.header.HeaderWriterFilter@33dcbdc2, org.springframework.security.web.csrf.CsrfFilter@522fdf0c, org.springframework.security.web.authentication.logout.LogoutFilter@365ad794, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@23df16cf, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@227cba85, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@b38dc7d, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@142422a4, org.springframework.security.web.session.SessionManagementFilter@2f0b7b6d, org.springframework.security.web.access.ExceptionTranslationFilter@74bca236, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@30587737]
2022-01-18 17:38:44,691 INFO org.springframework.security.web.DefaultSecurityFilterChain [main] Creating filter chain: NegatedRequestMatcher [requestMatcher=Ant [pattern='/actuator/**']], [com.betex.auth.filters.CorsFilter@20a9f5fb, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@10e28d97, org.springframework.security.web.context.SecurityContextPersistenceFilter@c6b08a5, org.springframework.security.web.header.HeaderWriterFilter@5f05cd7e, org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter@2a54c92e, org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter@55b62db8, org.springframework.security.web.authentication.logout.LogoutFilter@274f51ad, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@54980154, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@25874884, org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter@8cb7185, org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter@4dac40b, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@37d43b9b, org.springframework.security.web.session.SessionManagementFilter@11e8e183, org.springframework.security.web.access.ExceptionTranslationFilter@56f1db5f, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@78543f0d]
当您扩展 KeycloakWebSecurityConfigurerAdapter
时,适配器会注册一个 KeycloakAuthenticationProcessingFilter
类型的 Bean。这个filter是在SpringSecurity的SecurityFilterChain
注册的,因为是Bean,所以在原链中SpringBoot也会自动注册,所以即使SpringSecurity不应用它,稍后将在原始过滤器链中应用它。
尝试禁止此过滤器被 Spring Boot 注册,像这样:
@Bean
public FilterRegistrationBean registration(KeycloakAuthenticationProcessingFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
此外,如果您使用的是 OAuth 2,您可以考虑使用 spring-security-oauth2-resource-server
并简化资源服务器的配置。看看 documentation。这样您就不需要扩展自定义适配器,只需依赖 Spring Security.