Jelajahi Sumber

add 增加 nacos sentinel snailjob 健康检查 actuator 账号密码认证

疯狂的狮子Li 2 tahun lalu
induk
melakukan
e1e5f8e519

+ 9 - 0
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:

+ 63 - 0
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() {
+    }
+
+}

+ 29 - 0
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<ActuatorAuthFilter> actuatorFilterRegistrationBean() {
+        FilterRegistrationBean<ActuatorAuthFilter> registrationBean = new FilterRegistrationBean<>();
+        registrationBean.setFilter(new ActuatorAuthFilter(username, password));
+        registrationBean.addUrlPatterns("/actuator", "/actuator/**");
+        return registrationBean;
+    }
+
+}

+ 2 - 0
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=*

+ 63 - 0
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() {
+    }
+
+}

+ 29 - 0
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<ActuatorAuthFilter> actuatorFilterRegistrationBean() {
+        FilterRegistrationBean<ActuatorAuthFilter> registrationBean = new FilterRegistrationBean<>();
+        registrationBean.setFilter(new ActuatorAuthFilter(username, password));
+        registrationBean.addUrlPatterns("/actuator", "/actuator/**");
+        return registrationBean;
+    }
+
+}

+ 64 - 0
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() {
+    }
+
+}

+ 29 - 0
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<ActuatorAuthFilter> actuatorFilterRegistrationBean() {
+        FilterRegistrationBean<ActuatorAuthFilter> registrationBean = new FilterRegistrationBean<>();
+        registrationBean.setFilter(new ActuatorAuthFilter(username, password));
+        registrationBean.addUrlPatterns("/actuator", "/actuator/**");
+        return registrationBean;
+    }
+
+}

+ 0 - 3
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@