Spring Boot Admin 修改日志级别时 403 Forbidden
昨天发现 Spring Boot Admin 中调整日志级别时报了 403 的错误。实际报错的请求地址为 /instances/e0ab022eca79/actuator/loggers/ROOT
,其中 e0ab022eca79 为实例的 ID , ROOT 是要修改的 Logger 的包。
经调查是由于启用了身份验证(使用的 spring-boot-starter-security 组件),导致在访问 /instances
时被拦截了。(不太理解为什么会被 CSRF 保护拦截,毕竟请求的仍然是当前 domain 的 URL 。)
修改 HttpSecurity
的配置对 /instances/**
端点禁用 CSRF 保护就可以修复这个问题了。官方提供的参考配置代码如下:[1]
java
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.util.UUID;
@Configuration(proxyBeanMethods = false)
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final AdminServerProperties adminServer;
private final SecurityProperties security;
public SecuritySecureConfig(AdminServerProperties adminServer, SecurityProperties security) {
this.adminServer = adminServer;
this.security = security;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(this.adminServer.path("/"));
http.authorizeRequests((authorizeRequests) -> authorizeRequests
// 授予对所有静态资产和登录页面的公共访问权限
.antMatchers(this.adminServer.path("/assets/**")).permitAll()
.antMatchers(this.adminServer.path("/actuator/info")).permitAll()
.antMatchers(this.adminServer.path("/actuator/health")).permitAll()
.antMatchers(this.adminServer.path("/login")).permitAll()
// 所有其他请求都必须经过身份验证
.anyRequest().authenticated()
)
// 配置登录和注销
.formLogin((formLogin) -> formLogin.loginPage(this.adminServer.path("/login")).successHandler(successHandler).and())
.logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout")))
// 启用 HTTP 基本支持。这是 Spring Boot Admin Client 注册所必需的。
.httpBasic(Customizer.withDefaults())
// 通过 Cookie 启用 CSRF 保护
.csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(
// 对 Spring Boot Admin Client 用于(取消)注册的端点禁用 CSRF 保护
new AntPathRequestMatcher(this.adminServer.path("/instances"), HttpMethod.POST.toString()),
new AntPathRequestMatcher(this.adminServer.path("/instances/*"), HttpMethod.DELETE.toString()),
// 对 actuator 端点禁用 CSRF 保护
new AntPathRequestMatcher(this.adminServer.path("/actuator/**"))
))
.rememberMe((rememberMe) -> rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600));
}
// Required to provide UserDetailsService for "remember functionality"
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser(security.getUser().getName())
.password("{noop}" + security.getUser().getPassword()).roles("USER");
}
}
如果是客户端报错,可以参考如下配置:[2]
java
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.ignoringAntMatchers("/actuator/**");
}