Spring Boot Actuator Endpoints 安全性不适用于自定义 Spring Security 配置
Posted
技术标签:
【中文标题】Spring Boot Actuator Endpoints 安全性不适用于自定义 Spring Security 配置【英文标题】:Spring Boot Actuator Endpoints security doesn't work with custom Spring Security Configuration 【发布时间】:2017-06-27 19:24:03 【问题描述】:这是我的 Spring Boot 1.5.1 Actuator application.properties
:
#Spring Boot Actuator
management.contextPath: /actuator
management.security.roles=R_0
这是我的WebSecurityConfig
:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService userDetailsService;
@Value("$logout.success.url")
private String logoutSuccessUrl;
@Override
protected void configure(HttpSecurity http) throws Exception
// @formatter:off
http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
http
.csrf().ignoringAntMatchers("/v1.0/**", "/logout")
.and()
.authorizeRequests()
.antMatchers("/oauth/authorize").authenticated()
//Anyone can access the urls
.antMatchers("/signin/**").permitAll()
.antMatchers("/v1.0/**").permitAll()
.antMatchers("/auth/**").permitAll()
.antMatchers("/actuator/health").permitAll()
.antMatchers("/actuator/**").hasAuthority("R_0")
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.failureUrl("/login?error=true")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl(logoutSuccessUrl)
.permitAll();
// @formatter:on
/**
* Configures the authentication manager bean which processes authentication requests.
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
现在我可以使用具有R_0
权限的正确用户成功登录我的应用程序,但是当我尝试访问时
http://localhost:8080/api/actuator/beans
我收到以下错误:
There was an unexpected error (type=Forbidden, status=403).
Access is denied. User must have one of the these roles: R_0
如何正确配置 Spring Boot Actuator 以了解正确的 Authentication
?
现在为了让它工作,我必须做以下技巧:
management.security.enabled=false
.antMatchers("/actuator/health").permitAll()
.antMatchers("/actuator/**").hasAuthority("R_0")
是否有机会以正确的方式配置执行器?
更新
我正在使用UserDetailsService.UserDetails.Authorities
public Collection<? extends GrantedAuthority> getAuthorities()
String[] authorities = permissions.stream().map(p ->
return p.getName();
).toArray(String[]::new);
return AuthorityUtils.createAuthorityList(authorities);
【问题讨论】:
谢谢,但我可以通过.antMatchers("/actuator/**").hasAuthority("R_0")
来管理这个问题。问题是我无法使用默认的 Spring Boot Actuator 安全集成,而无需提供像这样的自定义配置。
我遇到了同样的问题。请注意,通过在 AuthenticationManagerBuilder
上设置 UserDetailsService
会以某种方式覆盖默认安全配置,这意味着需要像通过 HttpSecurity
类所做的那样显式 URI 访问配置。您是否设法使其按您最初的预期工作?
是的,您必须为您的management.security.roles
使用前缀ROLE_
,例如management.security.roles=ROLE_SOMENAME
由于我使用的是 Spring Boot 1.3.5,因此我的问题与此属性的复数与单数格式有关。对于我的版本,您只能将一个角色定义为,例如management.security.role=ACTUATOR
,在 1.4.x 版本中已更改为复数等效项。此外,我为AuthenticationManagerBuilder
类的UserDetails
检索组合了两个来源,一个是我的服务用户的UserDetailsService
的实现,第二个是执行器和管理员用户的InMemoryUserDetailsManagerConfigurer
的实例(你可以逃脱也只有一个)。
【参考方案1】:
-
您可以添加以下属性
endpoints.health.enabled=true
endpoints.loggers.enabled=true
endpoints.metrics.enabled=true
endpoints.env.enabled=false
endpoints.configprops.enabled=false
endpoints.autoconfig.enabled=false
endpoints.info.enabled=false
management.context-path=/management
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ApplicationContextAware
private static final String ACTUATOR = "ACTUATOR";
private static final String ROLE1 = "USER";
@Override
protected void configure(HttpSecurity http) throws Exception
http.httpBasic().and().authorizeRequests().antMatchers("/controllerpath/**")
.hasAnyRole(ROLE1).antMatchers("/loggers/**","/metrics/**","/health/**").hasAnyRole(ACTUATOR).and()
.csrf().disable().headers().frameOptions().disable();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("username-of-app").password("encryptedpassword")
.roles(ROLE1).and().withUser("username-of-management-for-path")
.password("encrypted password").roles(ACTUATOR);
【讨论】:
【参考方案2】:1
1.You can add the following properties
endpoints.health.enabled=true
endpoints.loggers.enabled=true
endpoints.metrics.enabled=true
endpoints.env.enabled=false
endpoints.configprops.enabled=false
endpoints.autoconfig.enabled=false
endpoints.info.enabled=false
management.context-path=/management
2)
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ApplicationContextAware
private static final String ACTUATOR = "ACTUATOR";
private static final String ROLE1 = "USER";
@Override
protected void configure(HttpSecurity http) throws Exception
http.httpBasic().and().authorizeRequests().antMatchers("/controllerpath/**")
.hasAnyRole(ROLE1).antMatchers("/loggers/**","/metrics/**","/health/**").hasAnyRole(ACTUATOR).and()
.csrf().disable().headers().frameOptions().disable();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("username-of-app").password("encryptedpassword")
.roles(ROLE1).and().withUser("username-of-management-for-path")
.password("encrypted password").roles(ACTUATOR);
【讨论】:
【参考方案3】:我来自 Reactive Spring Boot 2.x 应用程序并遇到了这个问题,并通过更新 WebSecurityConfig.securityWebFilterChain 以及 SecurityContextRepository.load 以包含 /actuator/** 来解决它,如下所示:
public class WebSecurityConfig
private AuthenticationManager authenticationManager;
private SecurityContextRepository securityContextRepository;
@Autowired
public WebSecurityConfig(AuthenticationManager authenticationManager, SecurityContextRepository securityContextRepository)
this.authenticationManager = authenticationManager;
this.securityContextRepository = securityContextRepository;
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http)
return http
.exceptionHandling()
.authenticationEntryPoint((swe, e) -> Mono.fromRunnable(() ->
swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
)).accessDeniedHandler((swe, e) -> Mono.fromRunnable(() ->
swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
)).and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.authenticationManager(authenticationManager)
.securityContextRepository(securityContextRepository)
.authorizeExchange()
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated()
.and().build();
以及更新
@Slf4j
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository
private AuthenticationManager authenticationManager;
public SecurityContextRepository(AuthenticationManager authenticationManager)
this.authenticationManager = authenticationManager;
@Override
public Mono<Void> save(ServerWebExchange swe, SecurityContext sc)
return Mono.error(new UnsupportedOperationException("Not supported"));
@Override
public Mono<SecurityContext> load(ServerWebExchange swe)
ServerHttpRequest request = swe.getRequest();
if (request.getPath().value().startsWith("/actuator") )
return Mono.empty();
// other authentication logic here
【讨论】:
【参考方案4】:您必须为您的management.security.roles
使用前缀ROLE_
例如management.security.roles=ROLE_SOMENAME
才能解决此问题
【讨论】:
我认为在 Spring Boot 1.5.1 中management.security.roles
属性的值不应再以 ROLE_
为前缀。我发现很多关于这个主题的困惑。我相信您的问题也可以通过修改以下HttpSecurity
设置.antMatchers("/actuator/**").hasAuthority("ROLE_R_0")
来解决。
antMatcher 不能解决问题。例如,执行器/健康端点为授权用户和非授权用户返回不同的数据。基于提供的antMatcher配置无法实现
您所说的行为记录在docs.spring.io/spring-boot/docs/current/reference/html/… 的第 48.7 节中。您最初的问题是关于 /actuator/beans
呼叫的 403 状态代码。我相信可以通过删除antMatchers("/actuator...")
设置并确保UserDetailsService
返回包含GrantedAuthority
的UserDetails
对象来修复它,在您的情况下设置为ROLE_R_0
。或者,您可以将其与 InMemoryUserDetailsManagerConfigurer
结合使用,正如我在对主要问题的评论中提到的那样。
它不起作用,因为 Spring Boot Actuator 不理解没有 _ROLE 前缀的权限/角色。 antMatchers 在这里也没有帮助,因为为了使用它,我必须禁用 management.security。禁用此属性后,我将失去上面描述的执行器功能,因此您的解决方案对我完全没有任何意义。
更多详情请参考以下github问题github.com/spring-projects/spring-boot/issues/8255【参考方案5】:
要获得 Spring Boot 执行器端点的授权,您需要具有 ACTUATOR 角色。 参考这个例子Accessing Restricted Actuator Endpoints with Spring Security
【讨论】:
【参考方案6】:根据此链接:
http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-monitoring.html
默认情况下,所有敏感的 HTTP 端点都是安全的,因此只有 具有 ACTUATOR 角色的用户可以访问它们。强制执行安全性 使用标准的 HttpServletRequest.isUserInRole 方法。
如果需要,请使用 management.security.roles 属性 不同于 ACTUATOR。
所以我认为您所要做的就是在 application.properties 中设置以下属性。
management.security.roles
例如:
management.security.roles=R_0
【讨论】:
谢谢,但请看看我的问题。我已经提供了management.security.roles=R_0
问题是 Spring Boot Actuator 出于某种原因不了解如何使用当前的 Spring Security。以上是关于Spring Boot Actuator Endpoints 安全性不适用于自定义 Spring Security 配置的主要内容,如果未能解决你的问题,请参考以下文章
spring-boot-starter-actuator监控接口详解
Spring Boot 应用程序使用 spring-boot-starter-actuator 给出“无法启动 tomcat”异常