#spring-boot #spring-security #spring-webflux
Вопрос:
У меня есть приложение spring boot, которое использует JWT для всех конечных точек. Теперь я хочу добавить /actuator
конечную точку, которая использует базовую аутентификацию для включения показателей очистки prometheus.
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
class SecurityConfig(
val userService: UserService
) {
@Bean
fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain? {
return http {
csrf { disable() }
formLogin { disable() }
httpBasic { disable() }
authorizeExchange {
authorize(ServerWebExchangeMatchers.pathMatchers(HttpMethod.OPTIONS, "/**"), permitAll)
// the following should not use JWT but basic auth
authorize(ServerWebExchangeMatchers.pathMatchers("/actuator"), authenticated)
authorize(anyExchange, authenticated)
}
oauth2ResourceServer {
jwt {
jwtAuthenticationConverter = customConverter()
}
}
}
}
}
В стеке MVC я бы использовал что-то вроде этого:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Configuration
@Order(1)
public static class ActuatorWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Value("${management.endpoints.web.base-path}")
private String managementPath;
@Value("${config.actuator.user.name}")
private String actuatorUser;
@Value("${config.actuator.user.password}")
private String actuatorPassword;
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(actuatorUser)
.password(passwordEncoder().encode(actuatorPassword))
.authorities("ROLE_ACTUATOR");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new Argon2PasswordEncoder();
}
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher(managementPath "/**")
.cors().and()
.csrf().disable()
.authorizeRequests()
.anyRequest()
.hasRole("ACTUATOR")
.and()
.httpBasic();
}
}
@Configuration
@Order(2)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.authenticationProvider(...)
.authorizeRequests()
// ...
}
}
}
Как это переводится в webflux?
Комментарии:
1. Вы пробовали приготовить еще один боб и заказать его?
2. @Toerktumlare Я боролся с этим, но после того, как узнал, что для этого требуется использовать
securityMatcher
s в webflux, это работает! подробности смотрите в моем ответе.
Ответ №1:
Добавление нескольких компонентов возможно, но требует использования securityMatcher
:
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
class SecurityConfig(
val userService: UserService
) {
@Value("${config.actuator.user.name}")
private val actuatorUser: String? = null
@Value("${config.actuator.user.password}")
private val actuatorPassword: String? = null
@Bean
@Order(1)
fun springSecurityFilterChainActuator(http: ServerHttpSecurity): SecurityWebFilterChain? {
val encoder: PasswordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder()
return http {
securityMatcher(ServerWebExchangeMatchers.pathMatchers("/actuator/**"))
csrf { disable() }
formLogin { disable() }
httpBasic {
authenticationManager = UserDetailsRepositoryReactiveAuthenticationManager(
MapReactiveUserDetailsService(
User
.withUsername(actuatorUser)
.password(encoder.encode(actuatorPassword))
.roles("ACTUATOR")
.build()
)
)
}
authorizeExchange {
authorize(anyExchange, hasRole("ACTUATOR"))
}
}
}
@Bean
@Order(2)
fun springSecurityFilterChainApi(http: ServerHttpSecurity): SecurityWebFilterChain? {
return http {
securityMatcher(ServerWebExchangeMatchers.pathMatchers("/**"))
csrf { disable() }
formLogin { disable() }
httpBasic { disable() }
authorizeExchange {
authorize(ServerWebExchangeMatchers.pathMatchers(HttpMethod.OPTIONS, "/**"), permitAll)
authorize(anyExchange, authenticated)
}
oauth2ResourceServer {
jwt {
jwtAuthenticationConverter = customConverter()
}
}
}
}
}