文章目录
- Actuator
- 概述
- 官网入口
- 支持的埋点信息查询、修改
- 使用
- 访问actuator埋点信息添加账号密码登录验证
- 动态修改日志级别
Actuator
概述
官网入口
官网: https://docs.spring.io/spring-boot/docs/2.7.6/reference/html/actuator.html#actuator.endpoints
支持的埋点信息查询、修改
官网: https://docs.spring.io/spring-boot/docs/2.7.6/reference/html/actuator.html#actuator.endpoints
访问:
- 获取信息(Get):http://ip:端口号/actuator/埋点ID
- 修改信息(Post): http://ip:端口号/actuator/埋点ID/[[可能会有,比如修改日志时需要使用到]]
使用
访问actuator埋点信息添加账号密码登录验证
特别注意: 不要使用拦截器(HandlerInterceptor)进行拦截/actuator链接,因为拦不到,只能使用过滤器才能拦截到,我也不知道为什么
pom.xml - 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.yml
management:
endpoint:
beans:
enabled: true
health:
# 不开启仅有应用是否可用信息,开启了可以看到磁盘信息、数据库连接是否可用状态等其他组件信息
show-details: always
shutdown:
enabled: true
endpoints:
# 所有端点功能设置成默认都可用 == 开启了这个上面的配置如果不是false,可以不用设置
enabled-by-default: true
web:
cors:
allow-credentials: true
allowed-methods: '*'
allowed-origin-patterns: '*'
exposure:
# 所有端点都对外暴露可访问到
include: '*'
LrcUtilsWebApplication.java - 启动类-必须必须添加注解@ServletComponentScan,否则过滤器的路径匹配不生效
@ServletComponentScan
@SpringBootApplication
public class LrcUtilsWebApplication {
public static void main(String[] args) {
SpringApplication.run(LrcUtilsWebApplication.class, args);
}
}
ActuatorEndpointFilter.java - 账号密码过滤器
/**
* @author LinRuChang
* @version 1.0
* @date 2022/11/30
* @since 1.8
**/
@Slf4j
@WebFilter(filterName = "actuatorEndpointFilter", urlPatterns = {"/actuator/*"})
public class ActuatorEndpointFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//无需登录,可直接访问、修改埋点信息
if(!SpringUtil.getBean(SysDictService.class).getAuthActuatorSwitch()) {
chain.doFilter(request, response);
return;
}
boolean authStatusFlag = false;
String authorization = EnhanceSpringUtil.getCurrentRequestHeader("Authorization");
log.info("Actuator系统埋点认证信息【Authorization】:{}", authorization);
String authType = null;
String authInfoCredentials = null;
String userName = null;
List<String> authorizationInfos = StrUtil.splitTrim(authorization, StrUtil.SPACE);
if (CollUtil.size(authorizationInfos) == 2) {
authType = authorizationInfos.get(0);
authInfoCredentials = authorizationInfos.get(1);
if (StrUtil.isNotBlank(authInfoCredentials)) {
if (StrUtil.equalsAnyIgnoreCase(authType, "BASIC")) {
String authInfo = Base64.decodeStr(authInfoCredentials);
List<String> authInfos = StrUtil.splitTrim(authInfo, StrUtil.COLON);
userName = CollUtil.size(authInfos) >= 2 ? authInfos.get(0) : null;
String password = CollUtil.size(authInfos) >= 2 ? authInfos.get(1) : null;
// 这里自行获取数据库中的用户、密码信息进行校验是否正确
Dict dbUserInfo = getActuatorUserInfo(userName);
if (dbUserInfo != null && StrUtil.equals(password, dbUserInfo.getStr("password"))) {
authStatusFlag = true;
}
}
}
}
// 认证失败
if (!authStatusFlag) {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader("WWW-Authenticate", StrUtil.format("{} realm=\"请填写正确的Actuator管理员账号、密码信息\"", StrUtil.blankToDefault(authType, "BASIC")));
httpServletResponse.setStatus(401);
httpServletResponse.setHeader("Content-Type", RequestEnum.RequestContentTypeEnum.JSON.getCode());
ResponseResult<String> unauthorizedInfo = ResponseResult.unauthorized("请填写正确的Actuator管理员账号、密码信息");
httpServletResponse.getWriter().write(JSONUtil.toJsonStr(unauthorizedInfo));
return;
}
chain.doFilter(request, response);
}
public Dict getActuatorUserInfo(String loginName) {
SysDictService sysDictService = SpringUtil.getBean(SysDictService.class);
Dict actuatorConfig = sysDictService.getActuatorConfig();
if (StrUtil.equals(loginName, actuatorConfig.getStr("loginName"))) {
return actuatorConfig;
}
return null;
}
}
动态修改日志级别
//post请求
//全局日志级别修改
http://127.0.0.1:9999/actuator/loggers/ROOT
//请求体
{
"configuredLevel": "日志级别(忽略大小写)"
}
//局部日志级别修改
http://127.0.0.1:9999/actuator/loggers/类、包全限定名
//请求体
{
"configuredLevel": "日志级别(忽略大小写)"
}