利用 Spring Boot Admin 对 Spring Boot 应用监控以及配置认证

2022-09-21 10:19:54 浏览数 (1)

前言

Spring Boot Admin 是一个优秀的 Spring Boot 应用监控,可以查看应用的各项性能指标,修改日志级别(生产环境利器,不用动不动就上 Arthas),dump 线程等功能。如果是微服务可以使用 Eureka 来做服务的注册与发现,单体应用的话直接往 Spring Boot Admin 的 Server 端注册就行。

这里主要讲认证方面,毕竟生产环境开放接口是件很危险的事。Spring Boot Admin 采用的是 Spring Security,如果项目认证模块本来就用是 Spring Security,那倒简单许多。但如果项目使用的是其他认证框架,就需要配合使用了,这里拿 Shiro 举例。

创建监控服务端

导入依赖

代码语言:javascript复制
    <dependency>
      <groupId>de.codecentric</groupId>
      <artifactId>spring-boot-admin-server</artifactId>
      <version>${spring-boot-admin-server.version}</version>
    </dependency>
    <dependency>
      <groupId>de.codecentric</groupId>
      <artifactId>spring-boot-admin-server-ui</artifactId>
      <version>${spring-boot-admin-server.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  • 服务端需要提供操作界面,这里引入了spring-boot-admin-server-ui

application.yml

代码语言:javascript复制
spring:
  security:
    user:
      name: xxx
      password: xxx
  • 定义监控服务端的账号密码,用于访问监控管理界面和 Spring Boot Admin 的 Client 注册

启动类

代码语言:javascript复制
@EnableAdminServer
@SpringBootApplication
public class MonitorApplication {

    public static void main(String[] args) {
        SpringApplication.run(MonitorApplication.class, args);
    }

}
  • EnableAdminServer:启用 Spring Boot Admin 的服务端

监控服务端的认证配置

代码语言:javascript复制
@Configuration
@EnableWebSecurity
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {

    private final String adminContextPath;

    public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
        this.adminContextPath = adminServerProperties.getContextPath();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler();
        handler.setTargetUrlParameter("redirectTo");
        handler.setDefaultTargetUrl(this.adminContextPath   "/");

        // 启用HTTP-Basic支持。这是Spring Boot Admin Client注册所必需的
        http.httpBasic().and()
            // 授予对所有静态资产的公共访问权限
            .authorizeRequests().antMatchers(this.adminContextPath   "/assets/**").permitAll()
            // 授予对登录页面的公共访问权限
            .antMatchers(this.adminContextPath   "/login").permitAll().and()
            // 所有请求都需要验证登录
            .authorizeRequests().anyRequest().authenticated().and()
            // 登录表单
            .formLogin().loginPage(this.adminContextPath   "/login").successHandler(handler).and()
            // 登出表单
            .logout().logoutUrl(this.adminContextPath   "/logout").and().csrf()
            // Enables CSRF-Protection using Cookies
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).ignoringAntMatchers(
            // 将服务注册的接口暴露出去.
            this.adminContextPath   "/instances",
            this.adminContextPath   "/actuator/**");

        ;
    }
}

配置被监控的客户端

导入依赖

代码语言:javascript复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>${spring-boot-admin-starter-client.version}</version>
</dependency>

application.yml

代码语言:javascript复制
spring:
  profiles:
    active: test
  application:
    name: @project.artifactId@-${spring.profiles.active}-${server.port}
  # 服务监控 start
  boot:
    admin:
      client:
        #指定admin server的地址
        url: http://ip:port
        #如果admin server设置了密码,admin client也要密码才能注册到admin server上
        username: xxx
        password: xxx
        #以ip注册到admin server上,默认false使用hostname注册
        instance:
          # 告诉监控saver端,此客户端的地址,默认取的docker内部ip
          # 不同环境需要单独配置
          service-url: http://ip:${server.port}
          prefer-ip: true
          metadata:
            user:
              name: ${spring.security.user.name}
              password: ${spring.security.user.password}

  security:
    user:
      name: xxx
      password: xxx

management:
  #暴露actuator的全部endpoint(即/actuator系列路径),默认只暴露少数endpoint
  endpoints:
    web:
      exposure:
        include: "*"
  #显示节点健康的具体信息,/actuator/health默认只返回节点状态(up|down),不返回节点的具体信息
  endpoint:
    health:
      show-details: always
# 服务监控 end
  • @project.artifactId@-{spring.profiles.active}-{server.port}:定义应用名称,便于监控管理界面区分多节点应用。这里使用了pom.xml里的变量,具体方法可参考Maven构建配置和激活SpringBoot配置文件

配置 Spring Security 对暴露的应用状态信息接口做认证

代码语言:javascript复制
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 监控信息的接口
     */
    public static final String ACTUATOR_URL = "/actuator/**";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers(ACTUATOR_URL).authenticated()
            .and()
            .httpBasic();
    }
}
  • .csrf().disable():必须加这个,默认是启用了csrf,所有接口都会被拦截。我们这个项目是用 Shiro 来做认证模块的,所以 Spring Security 只需要管理应用状态信息接口就行

配置 Shiro ,放行应用状态信息接口

代码语言:javascript复制
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);

    // 配置不会被拦截的链接 顺序判断
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

    // 放开监控信息的接口,交给 Spring Security 管理
    filterChainDefinitionMap.put(SecurityConfig.ACTUATOR_URL, "anon");

    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;

访问监控管理界面

访问 Spring Boot Admin 的Server端:http://ip:port/,输入 Server 端配置的账号密码就能使用了。

0 人点赞