16.4 保护Actuator

16.4 保护Actuator

我们可能不想让别人窥探Actuator暴露的信息。另外,因为Actuator提供了一些操作来修改环境变量和日志级别,所以最好对Actuator进行保护,只有具有对应权限的客户端才能消费这些端点。

虽然保护Actuator端点非常重要,但是安全性本身并不是Actuator的职责,我们需要使用Spring Security来保护Actuator。因为Actuator端点的路径和应用本身的路径非常相似,所以保护Actuator与保护其他的应用路径并没有什么区别。我们在第4章讨论的内容依然适用于保护Actuator端点。

因为所有的端点都集中在“/actuator”基础路径(如果设置了management.endpoints.web.base-path属性,那么可能会是其他的路径)下,所以很容易将授权规则应用到所有的Actuator端点上。例如,只有具有ROLE_ADMIN权限的用户才能调用Actuator端点,那么我们可以重写WebSecurityConfigurerAdapter的configure()方法:

1
2
3
4
5
6
7
8
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/actuator/**").hasRole("ADMIN")
.and()
.httpBasic();
}

这需要所有的请求均由具备ROLE_ADMIN权限的授权用户发起,才能进行访问。它还配置了HTTP basic认证,这样客户端应用可以在请求的Authorization头信息中提交编码后的认证信息。

保护Actuator的唯一问题在于,端点的路径硬编码为“/actuator/**”,如果因为修改了management.endpoints.web.base-path属性发生变化的话,那么这种方式就无法正常运行了。为了帮助解决这个问题,Spring Boot提供了EndpointRequest(一个请求匹配类,更简单,而且不依赖于给定的String路径)。借助EndpointRequest,我们可以将相同的安全要求用到Actuator上,而且不需要硬编码路径:

1
2
3
4
5
6
7
8
9
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(EndpointRequest.toAnyEndpoint())
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}

EndpointRequest.toAnyEndpoint()方法会返回一个请求匹配器,它会匹配所有的Actuator端点。如果你想要将某些端点从请求匹配器中移除,那么我们可以调用excluding()方法,通过名称进行声明:

1
2
3
4
5
6
7
8
9
10
11
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(
EndpointRequest.toAnyEndpoint()
.excluding("health", "info"))
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}

另外,如果我们只是想将安全性用到其中一部分Actuator端点中,那么可以调用to()来替换toAnyEndpoint(),并使用名称指明这些端点:

1
2
3
4
5
6
7
8
9
10
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(EndpointRequest.to(
"beans", "threaddump", "loggers"))
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}

这样会限制只将安全性功能用到“/beans”“/threaddump”和“/loggers”端点上,其他的Actuator端点会全部对外开放。