原由:风险检测扫出漏洞
访问http://xxx.xx.x/actuator 会直接获取到系统监控信息,存在安全问题,禁用actuator
1.禁用/env接口
缺点:谁都不可以访问不够灵活
会展示部分信息,漏扫严格的话建议替换其他方法
management: endpoint: env: enabled: false
2.直接屏蔽所有端口
缺点:谁都不可以访问不够灵活
management: endpoints: web: exposure: include: "*" enabled-by-default: false
3.引入spring-boot-starter-security依赖,增加登录认证
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
配置文件增加
spring: security: user: name: admin password: admin management: server: port: 8099 endpoints: web: exposure: include: "*"
4.添加全局过滤拦截类,增加登录认证
在项目目录新建config文件夹,新建下面两个文件
1. ActuatorFilter
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Base64; import java.util.Enumeration; public class ActuatorFilter implements Filter { public static final Logger logger = LoggerFactory.getLogger(ActuatorFilter.class); public static final String ACTUATOR_SESSION = "ActuatorBasicAuthSession"; private String userName; private String password; @Override public void init(FilterConfig filterConfig) throws ServletException { Enumeration<String> enumeration = filterConfig.getInitParameterNames(); if (enumeration.hasMoreElements()) { this.userName = filterConfig.getInitParameter("actuatorUserName"); this.password = filterConfig.getInitParameter("actuatorPassword"); } logger.info("ActuatorFilter init success"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String path = request.getRequestURI(); //可以把所有暴露出来的端点路径放在一个集合里面进行判断 if (path.startsWith("/actuator")) { Object actuatorSessionValue = request.getSession().getAttribute(ACTUATOR_SESSION); if (actuatorSessionValue == null || !userName.equals(actuatorSessionValue)) { String auth = request.getHeader("Authorization"); if (auth != null && !"".equals(auth)) { //解析认证参数 String userAndPass = this.decodeBase64(auth.substring(6)); String[] upArr = userAndPass.split(":"); if (upArr.length != 2) { this.writeForbiddenCode(response); return; } String iptUser = upArr[0]; String iptPass = upArr[1]; if (iptUser.equals(this.userName) && iptPass.equals(this.password)) { request.getSession().setAttribute(ACTUATOR_SESSION, this.userName); filterChain.doFilter(request, response); return; } this.writeForbiddenCode(response); return; } else { this.writeForbiddenCode(response); return; } } } filterChain.doFilter(request, response); } /** * 未认证时返回401认证页面 * * @param httpServletResponse * @throws IOException */ private void writeForbiddenCode(HttpServletResponse httpServletResponse) throws IOException { httpServletResponse.setStatus(401); httpServletResponse.setHeader("WWW-Authenticate", "Basic realm=\"input Actuator Basic userName & password \""); httpServletResponse.getWriter().write("没有权限访问当前资源"); } private String decodeBase64(String source) { String decodeStr = null; if (source != null) { try { byte[] bytes = Base64.getDecoder().decode(source); decodeStr = new String(bytes); } catch (Exception var4) { this.logger.error(var4.getMessage(), var4); } } return decodeStr; } }
2. WebMvcConfig
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Bean public FilterRegistrationBean actuatorFilter () { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new ActuatorFilter()); registrationBean.setName("actuator"); registrationBean.addUrlPatterns("/*"); registrationBean.setOrder(Integer.MAX_VALUE); //用户名密码可以配置在配置文件中或者配置中心 registrationBean.addInitParameter("actuatorUserName", "admin"); registrationBean.addInitParameter("actuatorPassword", "123456"); return registrationBean; } }
配置文件增加
management: endpoints: web: exposure: include: "*" endpoint: health: show-details: always
- never:不展示详细信息,up或者down的状态,默认配置
- when-authorized:详细信息将会展示给通过认证的用户。授权的角色可以通过
management.endpoint.health.roles
配置- always:对所有用户暴露详细信息
建议用方法3增加security的认证