From e1e5f8e519d8b93efd89eef5aafebea6bc0ce046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 25 Jul 2024 13:12:10 +0800 Subject: [PATCH] =?UTF-8?q?add=20=E5=A2=9E=E5=8A=A0=20nacos=20sentinel=20s?= =?UTF-8?q?nailjob=20=E5=81=A5=E5=BA=B7=E6=A3=80=E6=9F=A5=20actuator=20?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E5=AF=86=E7=A0=81=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/nacos/ruoyi-snailjob-server.yml | 9 +++ .../nacos/config/ActuatorAuthFilter.java | 63 ++++++++++++++++++ .../alibaba/nacos/config/SecurityConfig.java | 29 +++++++++ .../src/main/resources/application.properties | 2 + .../dashboard/filter/ActuatorAuthFilter.java | 63 ++++++++++++++++++ .../dashboard/filter/SecurityConfig.java | 29 +++++++++ .../starter/config/ActuatorAuthFilter.java | 64 +++++++++++++++++++ .../server/starter/config/SecurityConfig.java | 29 +++++++++ .../src/main/resources/application.yml | 3 - 9 files changed, 288 insertions(+), 3 deletions(-) create mode 100644 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/config/ActuatorAuthFilter.java create mode 100644 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/config/SecurityConfig.java create mode 100644 ruoyi-visual/ruoyi-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/ActuatorAuthFilter.java create mode 100644 ruoyi-visual/ruoyi-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/SecurityConfig.java create mode 100644 ruoyi-visual/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/config/ActuatorAuthFilter.java create mode 100644 ruoyi-visual/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/config/SecurityConfig.java diff --git a/config/nacos/ruoyi-snailjob-server.yml b/config/nacos/ruoyi-snailjob-server.yml index 4440fc4f..cc9c1ed8 100644 --- a/config/nacos/ruoyi-snailjob-server.yml +++ b/config/nacos/ruoyi-snailjob-server.yml @@ -13,6 +13,15 @@ spring: idle-timeout: 600000 max-lifetime: 900000 keepaliveTime: 30000 + cloud: + nacos: + discovery: + metadata: + # 解决 er 服务有 context-path 无法监控问题 + management.context-path: ${server.servlet.context-path}/actuator + # 监控账号密码 + username: ruoyi + userpassword: 123456 # snail-job 服务端配置 snail-job: diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/config/ActuatorAuthFilter.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/config/ActuatorAuthFilter.java new file mode 100644 index 00000000..1b857c39 --- /dev/null +++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/config/ActuatorAuthFilter.java @@ -0,0 +1,63 @@ +package com.alibaba.nacos.config; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class ActuatorAuthFilter implements Filter { + + private final String username; + private final String password; + + public ActuatorAuthFilter(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + + // 获取 Authorization 头 + String authHeader = request.getHeader("Authorization"); + + if (authHeader == null || !authHeader.startsWith("Basic ")) { + // 如果没有提供 Authorization 或者格式不对,则返回 401 + response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + return; + } + + // 解码 Base64 编码的用户名和密码 + String base64Credentials = authHeader.substring("Basic ".length()); + byte[] credDecoded = Base64.getDecoder().decode(base64Credentials); + String credentials = new String(credDecoded, StandardCharsets.UTF_8); + String[] split = credentials.split(":"); + if (split.length != 2) { + response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + return; + } + // 验证用户名和密码 + if (!username.equals(split[0]) && password.equals(split[1])) { + response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + return; + } + // 如果认证成功,继续处理请求 + filterChain.doFilter(request, response); + } + + @Override + public void init(FilterConfig filterConfig) { + } + + @Override + public void destroy() { + } + +} diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/config/SecurityConfig.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/config/SecurityConfig.java new file mode 100644 index 00000000..e38ae3f6 --- /dev/null +++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/config/SecurityConfig.java @@ -0,0 +1,29 @@ +package com.alibaba.nacos.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 权限安全配置 + * + * @author Lion Li + */ +@Configuration +public class SecurityConfig { + + @Value("${spring.boot.admin.client.username}") + private String username; + @Value("${spring.boot.admin.client.password}") + private String password; + + @Bean + public FilterRegistrationBean actuatorFilterRegistrationBean() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new ActuatorAuthFilter(username, password)); + registrationBean.addUrlPatterns("/actuator", "/actuator/**"); + return registrationBean; + } + +} diff --git a/ruoyi-visual/ruoyi-nacos/src/main/resources/application.properties b/ruoyi-visual/ruoyi-nacos/src/main/resources/application.properties index fa4b52de..f4b94fcf 100644 --- a/ruoyi-visual/ruoyi-nacos/src/main/resources/application.properties +++ b/ruoyi-visual/ruoyi-nacos/src/main/resources/application.properties @@ -88,6 +88,8 @@ spring.boot.admin.client.url=http://127.0.0.1:9100 spring.boot.admin.client.username=ruoyi spring.boot.admin.client.password=123456 spring.boot.admin.client.instance.service-host-type=IP +spring.boot.admin.client.instance.metadata.username: ${spring.boot.admin.client.username} +spring.boot.admin.client.instance.metadata.userpassword: ${spring.boot.admin.client.password} ### Metrics for prometheus management.endpoints.web.exposure.include=* diff --git a/ruoyi-visual/ruoyi-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/ActuatorAuthFilter.java b/ruoyi-visual/ruoyi-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/ActuatorAuthFilter.java new file mode 100644 index 00000000..715af041 --- /dev/null +++ b/ruoyi-visual/ruoyi-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/ActuatorAuthFilter.java @@ -0,0 +1,63 @@ +package com.alibaba.csp.sentinel.dashboard.filter; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class ActuatorAuthFilter implements Filter { + + private final String username; + private final String password; + + public ActuatorAuthFilter(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + + // 获取 Authorization 头 + String authHeader = request.getHeader("Authorization"); + + if (authHeader == null || !authHeader.startsWith("Basic ")) { + // 如果没有提供 Authorization 或者格式不对,则返回 401 + response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + return; + } + + // 解码 Base64 编码的用户名和密码 + String base64Credentials = authHeader.substring("Basic ".length()); + byte[] credDecoded = Base64.getDecoder().decode(base64Credentials); + String credentials = new String(credDecoded, StandardCharsets.UTF_8); + String[] split = credentials.split(":"); + if (split.length != 2) { + response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + return; + } + // 验证用户名和密码 + if (!username.equals(split[0]) && password.equals(split[1])) { + response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + return; + } + // 如果认证成功,继续处理请求 + filterChain.doFilter(request, response); + } + + @Override + public void init(FilterConfig filterConfig) { + } + + @Override + public void destroy() { + } + +} diff --git a/ruoyi-visual/ruoyi-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/SecurityConfig.java b/ruoyi-visual/ruoyi-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/SecurityConfig.java new file mode 100644 index 00000000..2bed7dbd --- /dev/null +++ b/ruoyi-visual/ruoyi-sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/filter/SecurityConfig.java @@ -0,0 +1,29 @@ +package com.alibaba.csp.sentinel.dashboard.filter; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 权限安全配置 + * + * @author Lion Li + */ +@Configuration +public class SecurityConfig { + + @Value("${spring.cloud.nacos.discovery.metadata.username}") + private String username; + @Value("${spring.cloud.nacos.discovery.metadata.userpassword}") + private String password; + + @Bean + public FilterRegistrationBean actuatorFilterRegistrationBean() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new ActuatorAuthFilter(username, password)); + registrationBean.addUrlPatterns("/actuator", "/actuator/**"); + return registrationBean; + } + +} diff --git a/ruoyi-visual/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/config/ActuatorAuthFilter.java b/ruoyi-visual/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/config/ActuatorAuthFilter.java new file mode 100644 index 00000000..799b8ab5 --- /dev/null +++ b/ruoyi-visual/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/config/ActuatorAuthFilter.java @@ -0,0 +1,64 @@ +package com.aizuda.snailjob.server.starter.config; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class ActuatorAuthFilter implements Filter { + + private final String username; + private final String password; + + public ActuatorAuthFilter(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + + // 获取 Authorization 头 + String authHeader = request.getHeader("Authorization"); + + if (authHeader == null || !authHeader.startsWith("Basic ")) { + // 如果没有提供 Authorization 或者格式不对,则返回 401 + response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + return; + } + + // 解码 Base64 编码的用户名和密码 + String base64Credentials = authHeader.substring("Basic ".length()); + byte[] credDecoded = Base64.getDecoder().decode(base64Credentials); + String credentials = new String(credDecoded, StandardCharsets.UTF_8); + String[] split = credentials.split(":"); + if (split.length != 2) { + response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + return; + } + // 验证用户名和密码 + if (!username.equals(split[0]) && password.equals(split[1])) { + response.setHeader("WWW-Authenticate", "Basic realm=\"realm\""); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); + return; + } + // 如果认证成功,继续处理请求 + filterChain.doFilter(request, response); + } + + @Override + public void init(FilterConfig filterConfig) { + } + + @Override + public void destroy() { + } + +} diff --git a/ruoyi-visual/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/config/SecurityConfig.java b/ruoyi-visual/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/config/SecurityConfig.java new file mode 100644 index 00000000..7b8f5640 --- /dev/null +++ b/ruoyi-visual/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/config/SecurityConfig.java @@ -0,0 +1,29 @@ +package com.aizuda.snailjob.server.starter.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 权限安全配置 + * + * @author Lion Li + */ +@Configuration +public class SecurityConfig { + + @Value("${spring.cloud.nacos.discovery.metadata.username}") + private String username; + @Value("${spring.cloud.nacos.discovery.metadata.userpassword}") + private String password; + + @Bean + public FilterRegistrationBean actuatorFilterRegistrationBean() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new ActuatorAuthFilter(username, password)); + registrationBean.addUrlPatterns("/actuator", "/actuator/**"); + return registrationBean; + } + +} diff --git a/ruoyi-visual/ruoyi-snailjob-server/src/main/resources/application.yml b/ruoyi-visual/ruoyi-snailjob-server/src/main/resources/application.yml index 69295f3a..4ce70334 100644 --- a/ruoyi-visual/ruoyi-snailjob-server/src/main/resources/application.yml +++ b/ruoyi-visual/ruoyi-snailjob-server/src/main/resources/application.yml @@ -50,9 +50,6 @@ spring: # 注册组 group: @nacos.discovery.group@ namespace: ${spring.profiles.active} - metadata: - # 解决 er 服务有 context-path 无法监控问题 - management.context-path: ${server.servlet.context-path}/actuator config: # 配置组 group: @nacos.config.group@