diff --git a/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/SgzbGatewayApplication.java b/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/SgzbGatewayApplication.java index 50beecb..205cbf0 100644 --- a/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/SgzbGatewayApplication.java +++ b/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/SgzbGatewayApplication.java @@ -5,6 +5,7 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.web.servlet.ServletComponentScan; import javax.annotation.Resource; @@ -14,6 +15,7 @@ import javax.annotation.Resource; * @author ruoyi */ @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) + public class SgzbGatewayApplication implements CommandLineRunner { public static void main(String[] args) { diff --git a/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/filter/SecurityHeaderFilter.java b/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/filter/SecurityHeaderFilter.java new file mode 100644 index 0000000..82bb570 --- /dev/null +++ b/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/filter/SecurityHeaderFilter.java @@ -0,0 +1,116 @@ +package com.bonus.sgzb.gateway.filter; + +/** + * @author 30791 + * @version 1.0 + * Create by 2025/10/22 10:41 + */ + +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.HttpHeaders; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.List; + + +@Slf4j +@Component +public class SecurityHeaderFilter implements GlobalFilter, Ordered { + + // 定义需要添加安全头的页面路径 + private static final List PROTECTED_PATH_PREFIXES = Arrays.asList( + "/login", "/admin", "/PMA", "/html", "/sitemap.xml", + "/db", "/dbadmin", "/myadmin", "/mysql", "/mysqladmin", + "/phpMyAdmin", "/phpMyAdmin2" + ); + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + ServerHttpResponse response = exchange.getResponse(); + String path = request.getPath().value(); + String method = request.getMethod().name(); + + log.debug("SecurityHeaderFilter 处理请求: {} {}", method, path); + + // 获取响应头 + HttpHeaders headers = response.getHeaders(); + + // 检查是否为受保护的路径 + boolean isProtectedPage = isProtectedPath(path); + + + // 设置 Referrer-Policy(所有请求都应用) + headers.set("Referrer-Policy", "strict-origin-when-cross-origin"); + + if (isProtectedPage) { + // 添加点击劫持防护头 + headers.add("X-Frame-Options", "DENY"); + // 改成完整的 CSP,仍保留“禁止被嵌套” + headers.add("Content-Security-Policy", + "default-src 'self'; " + // 默认仅本域 + "script-src 'self' https://code.jquery.com; " + // 允许 jQuery CDN + "style-src 'self' 'unsafe-inline'; " + // 本域 CSS + 内联 + "img-src 'self' data:; " + // 本域图片、data URI + "frame-ancestors 'none'"); // 继续禁止被 iframe + // 添加其他推荐的安全头 +// headers.add("X-Content-Type-Options", "nosniff"); +// headers.add("X-XSS-Protection", "1; mode=block"); +// headers.add("Strict-Transport-Security", "max-age=31536000; includeSubDomains"); + + log.info("为受保护路径 {} 添加严格安全头部", path); + + // 调试日志 + if (log.isDebugEnabled()) { + log.debug("设置的严格安全头部:"); + log.debug(" X-Frame-Options: DENY"); + log.debug(" Content-Security-Policy: frame-ancestors 'none'"); + } + } else { + // 即使不是受保护路径,也添加基本安全头 + headers.add("X-Frame-Options", "SAMEORIGIN"); + // 改成完整的 CSP,仍保留“禁止被嵌套” + headers.add("Content-Security-Policy", + "default-src 'self'; " + // 默认仅本域 + "script-src 'self' https://code.jquery.com; " + // 允许 jQuery CDN + "style-src 'self' 'unsafe-inline'; " + // 本域 CSS + 内联 + "img-src 'self' data:; " + // 本域图片、data URI + "frame-ancestors 'none'"); // 继续禁止被 iframe + //headers.add("X-Content-Type-Options", "nosniff"); + //headers.add("X-XSS-Protection", "1; mode=block"); + + log.debug("为普通路径 {} 添加基本安全头部", path); + } + + // 继续执行过滤器链 + return chain.filter(exchange); + } + + @Override + public int getOrder() { + // 设置过滤器执行顺序,数字越小优先级越高 + // 设置为高位值,确保在路由之后执行,能够修改响应头 + return Ordered.LOWEST_PRECEDENCE; + } + + /** + * 检查请求路径是否为受保护路径 + */ + private boolean isProtectedPath(String requestPath) { + for (String prefix : PROTECTED_PATH_PREFIXES) { + if (requestPath.startsWith(prefix)) { + log.debug("路径 {} 匹配受保护前缀: {}", requestPath, prefix); + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/SgzbSystemApplication.java b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/SgzbSystemApplication.java index b4881fd..2d7db75 100644 --- a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/SgzbSystemApplication.java +++ b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/SgzbSystemApplication.java @@ -7,6 +7,7 @@ import com.bonus.sgzb.common.security.annotation.EnableCustomConfig; import com.bonus.sgzb.common.security.annotation.EnableRyFeignClients; import com.bonus.sgzb.common.swagger.annotation.EnableCustomSwagger2; import org.springframework.boot.web.servlet.MultipartConfigFactory; +import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.context.annotation.Bean; import org.springframework.util.unit.DataSize; @@ -22,6 +23,7 @@ import javax.servlet.MultipartConfigElement; @EnableRyFeignClients @SpringBootApplication @EnableEncryptableProperties + public class SgzbSystemApplication { public static void main(String[] args) { SpringApplication.run(SgzbSystemApplication.class, args); diff --git a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysUserController.java b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysUserController.java index ea9d27c..f1ab5d9 100644 --- a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysUserController.java +++ b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysUserController.java @@ -181,6 +181,7 @@ public class SysUserController extends BaseController { // 权限集合 Set permissions = permissionService.getMenuPermission(user); AjaxResult ajax = AjaxResult.success(); + user.setPassword(""); ajax.put("user", user); ajax.put("roles", roles); ajax.put("permissions", permissions);