【一】什么是DDoS攻击
【1】DDoS攻击的概念
DDoS 的全称是 Distributed Denial-of-Service,即 分布式拒绝服务攻击。
(1)拒绝服务(DoS):
目标:攻击者的目的不是窃取数据或入侵系统,而是让正常的用户无法访问目标服务,也就是“拒绝”提供“服务”。
比喻:这就像你开了一家商店,攻击者不是来偷东西,而是雇了成百上千人堵在你的店门口。真正的顾客根本无法进门,你的生意也就瘫痪了。
(2)分布式(D):
手段:攻击不是来自一个源头,而是来自分布在全世界成千上万台被黑客控制的设备(如电脑、服务器、物联网摄像头、智能家居设备等)。这些设备组成了一个“僵尸网络”。
比喻:堵门的不是一伙人,而是从全国各地雇来的人,让你根本无法通过拦住一两个人来解决问题。
(3)简单总结
DDoS攻击就是攻击者指挥一个由大量计算机组成的“僵尸网络”,向一个特定的目标(如网站、服务器、网络设备)发动洪水般的垃圾请求,耗尽其所有资源(如网络带宽、系统CPU/内存、应用处理能力),从而导致合法用户无法获得服务的攻击方式。
【2】DDoS攻击的主要类型
(1)流量型攻击
网络层/传输层
用巨大的垃圾数据流堵塞目标服务器的网络管道(带宽)。
(2)协议型攻击
网络层/传输层
利用网络协议(如TCP三次握手)的缺陷,耗尽服务器的连接资源。
(3)应用层攻击
应用层
模仿正常用户行为,向消耗大的网页(如搜索、登录)发起频繁请求,耗尽CPU/内存资源。
【3】DDoS攻击的常见表现
(1)网络和系统层面表现
(1)网络严重拥塞,带宽耗尽:
表现:服务器的入口带宽使用率突然飙升到95%甚至100%,而出站带宽可能正常。监控图表会显示一个极高的峰值。
结果:服务器与外部网络的连接变得极慢或完全中断,SSH远程连接都可能卡顿或断开。
(2)服务器资源耗尽:
1-CPU使用率100%:尤其是应用层攻击,大量请求需要服务器进行业务逻辑处理,导致CPU不堪重负。
2-内存耗尽:每个请求都会占用一定的内存,海量并发请求会快速吃光所有可用内存。
3-连接数耗尽:服务器操作系统或Web容器(如Tomcat、Nginx)的最大连接数被占满,无法再建立新的连接。查看网络连接会看到成千上万的ESTABLISHED、SYN_RECV状态的连接(尤其是协议攻击)。
(2)应用和服务层面表现
(1)服务响应极其缓慢或完全无响应:
1-表现:网站、API接口的响应时间从几十毫秒飙升到几秒、几十秒,甚至直接超时。
2-结果:前端页面一直处于“加载中”,移动App无法刷新内容,用户体验极差。
(2)大量错误和异常:
1-5xx错误激增:如 502 Bad Gateway(网关后端服务无响应)、503 Service Unavailable(服务不可用)、504 Gateway Timeout(网关超时)。
2-4xx错误激增:在网关层或防护设备启动防护后,会返回大量 429 Too Many Requests(请求过快)或 403 Forbidden(IP被禁止)。
(3)微服务架构中的连锁反应:
1-表现:在Spring Cloud微服务体系中,一个服务(如网关或用户服务)被攻击瘫痪,可能通过依赖关系引发雪崩效应。
2-示例:网关被压垮 → 所有服务不可用;用户服务被压垮 → 依赖用户认证的订单、支付等服务全部报错;数据库连接池被占满 → 所有需要数据库的服务全部瘫痪。
(4)日志中出现异常模式:
1-来自少量IP的海量请求:在应用日志中,你会发现同一个IP地址在极短时间内对同一个接口(特别是耗时的接口,如搜索、导出)发起成千上万次请求。
2-User-Agent异常:大量请求使用奇怪或统一的恶意User-Agent。
3-无Referer或异常Referer:请求缺乏来源页信息或来源页是伪造的。
(3)监控告警系统的表现
一个健全的监控系统会在攻击发生时发出明确的警报:
(1)流量告警:网络流量超过预设阈值。
(2)QPS(每秒查询率)告警:API请求量异常飙升。
(3)错误率告警:HTTP 5xx/4xx错误率大幅上升。
(4)资源告警:CPU、内存、磁盘I/O使用率告警。
(5)健康检查失败:服务注册中心(如Eureka、Nacos)连续收到某个服务下线的心跳,导致该服务从服务列表中剔除。
【4】总结
DDoS攻击的核心表现可以概括为:在没有任何明显业务增长的情况下,系统各项资源指标(带宽、CPU、内存、连接数)突然达到极限,导致服务对正常用户变得极慢或完全不可用,并伴随大量错误日志和监控告警。
【二】DDoS 攻击类型与防护架构
【1】攻击类型识别
【2】防护体系架构
【三】基础设施层防护
【1】云服务商防护配置
- # 阿里云DDoS高防配置示例
- aliyun:
- ddos:
- basic:
- enable: true
- threshold: 5000 # 5Gbps触发清洗
- bgp:
- enable: true # 启用BGP高防IP
- waf:
- enable: true
- rules:
- cc-protection:
- enable: true
- threshold: 1000 # 单IP每秒请求阈值
复制代码
【2】CDN 动态加速配置
- @Configuration
- public class CdnConfig {
-
- @Bean
- public FilterRegistrationBean<CdnFilter> cdnFilter() {
- FilterRegistrationBean<CdnFilter> registration = new FilterRegistrationBean<>();
- registration.setFilter(new CdnFilter());
- registration.addUrlPatterns("/*");
- registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
- return registration;
- }
- }
- // CDN头验证过滤器
- public class CdnFilter implements Filter {
- private final Set<String> cdnIps = Set.of("1.1.1.1", "2.2.2.2"); // CDN IP段
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- String clientIp = getRealClientIp(httpRequest);
-
- // 验证CDN头部
- if (!isFromCdn(httpRequest, clientIp)) {
- ((HttpServletResponse) response).setStatus(403);
- return;
- }
-
- chain.doFilter(request, response);
- }
-
- private String getRealClientIp(HttpServletRequest request) {
- String ip = request.getHeader("X-Forwarded-For");
- if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
- ip = request.getHeader("X-Real-IP");
- }
- return ip != null ? ip : request.getRemoteAddr();
- }
-
- private boolean isFromCdn(HttpServletRequest request, String clientIp) {
- // 验证CDN特定头部
- String cdnSecret = request.getHeader("X-CDN-Secret");
- return "valid-secret".equals(cdnSecret) && cdnIps.contains(clientIp);
- }
- }
复制代码
【四】Nginx流量网关
【五】API 网关层防护(Spring Cloud Gateway)
【1】限流配置:对服务限流
对服务配置限流
- spring:
- cloud:
- gateway:
- routes:
- - id: user_service
- uri: lb://user-service
- predicates:
- - Path=/api/users/**
- filters:
- - name: RequestRateLimiter
- args:
- redis-rate-limiter.replenishRate: 100 # 每秒令牌数
- redis-rate-limiter.burstCapacity: 200 # 令牌桶容量
- key-resolver: "#{@ipKeyResolver}"
- - name: RequestSize
- args:
- maxSize: 10MB
- - StripPrefix=1
- redis:
- host: localhost
- port: 6379
复制代码
【2】自定义限流策略
- @Configuration
- public class RateLimitConfig {
-
- @Bean
- public KeyResolver ipKeyResolver() {
- return exchange -> {
- String ip = Objects.requireNonNull(exchange.getRequest()
- .getRemoteAddress()).getAddress().getHostAddress();
- return Mono.just(ip);
- };
- }
-
- @Bean
- public KeyResolver apiKeyResolver() {
- return exchange -> {
- String apiKey = exchange.getRequest()
- .getHeaders().getFirst("X-API-Key");
- return Mono.just(apiKey != null ? apiKey : "anonymous");
- };
- }
-
- @Bean
- public KeyResolver userKeyResolver() {
- return exchange -> {
- String token = exchange.getRequest()
- .getHeaders().getFirst("Authorization");
- if (token != null && token.startsWith("Bearer ")) {
- String username = JwtUtil.extractUsername(token.substring(7));
- return Mono.just(username != null ? username : "anonymous");
- }
- return Mono.just("anonymous");
- };
- }
- }
复制代码
【3】全局过滤器防护:DDoS保护过滤器
(1)限制全局QPS,登录接口限制10,普通接口限制100,其他静态资源限制1000
(2)检查全局请求速率
(3)检查IP黑白名单
(4)用户代理检查
(5)路径防护,判断是否敏感路径,判断是否是无效请求
(6)请求频率检查
- @Component
- public class DdosProtectionFilter implements GlobalFilter, Ordered {
-
- private final RedisTemplate<String, String> redisTemplate;
- private final RateLimiter rateLimiter = RateLimiter.create(1000); // 全局QPS限制
-
- @Override
- public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
- ServerHttpRequest request = exchange.getRequest();
- String clientIp = getClientIp(request);
- String path = request.getPath().value();
-
- // 1. 全局速率限制
- if (!rateLimiter.tryAcquire()) {
- return tooManyRequests(exchange);
- }
-
- // 2. IP黑白名单检查
- if (isBlacklistedIp(clientIp)) {
- return forbidden(exchange);
- }
-
- // 3. 用户代理检查
- if (isSuspiciousUserAgent(request)) {
- return forbidden(exchange);
- }
-
- // 4. 路径防护
- if (isSensitivePath(path) && !isValidRequest(request)) {
- return forbidden(exchange);
- }
-
- // 5. 请求频率检查
- if (exceedsRateLimit(clientIp, path)) {
- return tooManyRequests(exchange);
- }
-
- return chain.filter(exchange);
- }
-
- private boolean exceedsRateLimit(String clientIp, String path) {
- String key = "rate_limit:" + clientIp + ":" + path;
- Long count = redisTemplate.opsForValue().increment(key);
- redisTemplate.expire(key, 1, TimeUnit.SECONDS);
- return count != null && count > getPathLimit(path);
- }
-
- private int getPathLimit(String path) {
- if (path.contains("/api/login")) return 10; // 登录接口严格限制
- if (path.contains("/api/")) return 100; // 普通API
- return 1000; // 静态资源
- }
- }
复制代码
【4】Gateway的配置案例
(1)HTTPS强制跳转与证书配置
- spring:
- cloud:
- gateway:
- httpclient:
- ssl:
- use-insecure-trust-manager: false # 禁用不安全证书
- trustedX509Certificates:
- - classpath:server.crt
- routes:
- - id: https_redirect
- uri: https://example.com
- predicates:
- - Path=/**
- filters:
- - RedirectTo=302, https://${host}:${server.port}${path} # HTTP自动跳HTTPS
- server:
- ssl:
- key-store: classpath:keystore.p12
- key-store-password: changeit
- key-store-type: PKCS12
- key-alias: gateway
复制代码
(2)CORS跨域安全配置
(1)跨域安全问题
跨域安全问题(Cross-Origin Resource Sharing Security)源于浏览器的同源策略(Same-Origin Policy),这是浏览器最基本的安全机制。当网页尝试访问与其自身源(协议+域名+端口)不同的资源时,浏览器会阻止这种跨域请求。
(2)跨域攻击场景一:CSRF(跨站请求伪造)
攻击者诱导用户访问恶意网站,该网站自动向目标网站发起请求(携带用户凭证Cookie),执行用户不知情的操作(转账、修改密码等)
(3)跨域攻击场景二:XSSI(跨站脚本包含)
通过
(4)配置的逻辑
1-config.addAllowedOrigin(“https://trusted-domain.com”);
精确指定可信域名,不允许任意源访问
2-config.setExposedHeaders(“Authorization”);
仅暴露必要头信息,用来传token令牌
3-config.addAllowedHeader(List.of(“Content-Type”,“Accept”));
- @Bean
- public CorsWebFilter corsFilter() {
- return new CorsWebFilter(source -> {
- CorsConfiguration config = new CorsConfiguration();
- config.setAllowCredentials(true);// 允许凭证
- config.addAllowedOrigin("https://trusted-domain.com");// 允许的源
- config.addAllowedMethod("*");// 允许所有HTTP方法
- config.addAllowedHeader("*");// 允许所有头
- config.setExposedHeaders(List.of("Authorization"));// 暴露的响应头
- config.setMaxAge(3600L);// 预检缓存时间(秒)
- return config;
- });
- }
复制代码
(3)请求限流防护(Redis令牌桶)
- spring:
- cloud:
- gateway:
- routes:
- - id: api_route
- uri: lb://user-service
- predicates:
- - Path=/api/**
- filters:
- - name: RequestRateLimiter
- args:
- redis-rate-limiter.replenishRate: 100 # 每秒令牌数
- redis-rate-limiter.burstCapacity: 200 # 突发容量
- key-resolver: "#{@ipKeyResolver}"
复制代码- @Bean
- public KeyResolver ipKeyResolver() {
- return exchange ->
- Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
- }
复制代码
(4)JWT认证过滤器
【一】执行流程
(1)拦截所有需要认证的请求
跳过不需要认证的路径(如登录、公开API)
(2)验证JWT令牌的签名、有效期和结构
1-从Authorization头提取Bearer Token
2-使用公钥验证令牌签名
3-验证exp声明,判断是否过期
4-验证令牌是否已被撤销
(3)将认证信息传递给下游服务
1-解析令牌中的用户信息(如用户ID、角色)
2-将用户信息添加到请求头,传递给下游服务
(4)处理无效令牌的请求
无效令牌:返回401 Unauthorizen
过期令牌:返回403 Forbidden
缺失令牌:返回400 Bad Request
【二】配置重点
(1)密钥管理
使用非对称加密(RS256)
使用强密钥,定期轮换密钥(通过JWKS端点)
(2)令牌撤销
实现令牌黑名单(Redis存储)
短期令牌+刷新令牌机制
(3)防御措施
防止令牌泄露:强制HTTPS,设置HttpOnly Cookie
限制令牌有效期:设置合理的exp时间(通常30分钟-2小时)
敏感操作要求重新认证
添加必要的安全头Authorization
结合API网关的限流功能防止暴力破解
【三】RS256算法优点
(1)非对称加密,性能相对较差
(2)公钥和私钥是分离的,用公钥加密,用私钥解密,保证私钥安全即可,前端可以用公钥验证而无需接触私钥,私钥可以集中保管在安全环境,即使公钥泄露也不影响整体安全
(3)秘钥长度256字节,保密性更高
(4)适用于多租户和开放平台
【四】token生成的原理
JWT由Header(头信息),PayLoad (用户信息),Signature(签名)三个部分组成
(1)Header:头信息
Header头信息主要声明加密算法
HS256:对称加密
RS256:非对称加密
(2)PayLoad:用户信息
指定了七个默认字段供选择
也可以自定义私有字段,但是不建议在此存放密码之类的敏感信息,因为此部分可以解码还原出原始内容。虽然它可以解码,但是也不能修改这个内容。
- iss:发行人
- exp:到期时间
- sub:主体
- aud:用户
- nbf:在此之前不可用
- iat:发布时间
- jti:JWT ID用于标识该JWT
复制代码
对其进行base64加密,得到Jwt的第二部分
(3)Signature:签名
此部分用于防止jwt内容被篡改。这个签证信息由三部分组成(由加密后的Header,加密后的PayLoad,加密后的签名三部分组成)。base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐加密,然后就构成了jwt的第三部分,每个部分直接使用"."来进行拼接
【五】token校验的原理
通过秘钥解析token,得到用户信息、头信息等,根据用户信息查询到对应库里的用户信息,然后用同样的加密算法加密,然后判断加密后的信息是否一致
- @Component
- public class JwtAuthFilter implements GlobalFilter {
-
- @Override
- public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
- // 从头信息获取token令牌
- String token = exchange.getRequest()
- .getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
- // 缺失令牌
- if (token == null || !token.startsWith("Bearer ")) {
- return unauthorized(exchange, "Missing token");
- }
-
- try {
- //
- Claims claims = Jwts.parserBuilder()
- .setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
- .build()
- .parseClaimsJws(token.substring(7))
- .getBody();
-
- exchange.getAttributes().put("user", claims.getSubject());
- return chain.filter(exchange);
- } catch (JwtException e) {
- return unauthorized(exchange, "Invalid token");
- }
- }
-
- private Mono<Void> unauthorized(ServerWebExchange exchange, String msg) {
- exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
- return exchange.getResponse().writeWith(
- Mono.just(exchange.getResponse().bufferFactory().wrap(msg.getBytes()))
- );
- }
- }
复制代码
(5)IP黑白名单控制
- spring:
- cloud:
- gateway:
- routes:
- - id: secure_route
- uri: lb://core-service
- predicates:
- - Path=/v1/**
- filters:
- - name: RemoteAddr
- args:
- sources:
- - 192.168.1.0/24
- - 10.0.0.1
- deny: 0.0.0.0/0 # 默认拒绝所有
复制代码
(6)敏感头信息过滤
- spring:
- cloud:
- gateway:
- default-filters:
- - RemoveRequestHeader=Cookie,Set-Cookie # 移除敏感头
- - AddResponseHeader=X-Content-Type-Options, nosniff
- - AddResponseHeader=X-Frame-Options, DENY
- routes:
- - id: proxy_route
- uri: lb://internal-service
- filters:
- - StripPrefix=1
- - RemoveRequestHeader=Authorization # 特定路由移除
复制代码
(7)请求大小限制
- spring:
- cloud:
- gateway:
- routes:
- - id: upload_route
- uri: lb://file-service
- predicates:
- - Path=/upload
- filters:
- - name: RequestSize
- args:
- maxSize: 10MB # 最大请求体限制
复制代码
(8)WAF集成(Web应用防火墙)
【一】sql注入检查
攻击者通过在应用程序的输入字段中插入恶意的SQL代码,从而欺骗数据库执行非法的SQL命令。这可能导致数据泄露、数据篡改、甚至数据库服务器被完全控制。
(1)检查请求参数(包括查询参数、请求体、路径变量等)中是否包含可疑的SQL关键字或特殊字符。
(2)使用正则表达式或字符串匹配来检测常见的SQL注入模式。
复杂的SQL注入攻击可能使用编码、注释等方式绕过简单的关键字匹配。因此,网关层的SQL注入防护通常作为一道基础防线,更深入的防护应该在应用层(如使用预编译语句、ORM框架等)实现。
【二】检查XSS攻击
XSS(跨站脚本攻击)是一种常见的网络安全漏洞,攻击者通过在网页中注入恶意脚本,当其他用户浏览该网页时,脚本执行,从而窃取用户信息、会话令牌或进行其他恶意操作。
(1)检查输入中是否包含可疑的HTML标签(如
- @Component
- public class WafFilter implements GlobalFilter {
-
- private final WafClient wafClient;
-
- @Override
- public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
- ServerHttpRequest request = exchange.getRequest();
-
- // 1. 检查SQL注入
- if (wafClient.detectSqlInjection(request.getQueryParams().toString())) {
- return blockRequest(exchange, "SQLi detected");
- }
-
- // 2. 检查XSS攻击
- if (request.getHeaders().values().stream()
- .anyMatch(header -> wafClient.detectXss(header.toString()))) {
- return blockRequest(exchange, "XSS detected");
- }
-
- return chain.filter(exchange);
- }
- }
复制代码
(9)OAuth2资源服务器配置
- spring:
- security:
- oauth2:
- resourceserver:
- jwt:
- issuer-uri: https://auth-server.com
- jwk-set-uri: https://auth-server.com/.well-known/jwks.json
复制代码- @Bean
- public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
- return http
- .authorizeExchange(exchanges -> exchanges
- .pathMatchers("/public/**").permitAll()
- .pathMatchers("/admin/**").hasAuthority("ROLE_ADMIN")
- .anyExchange().authenticated()
- )
- .oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt)
- .csrf().disable() // 在网关层禁用CSRF
- .build();
- }
复制代码
【六】应用层防护(Spring Boot)
【1】自定义限流注解:对接口限流
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface RateLimit {
- int value() default 100; // 请求次数
- int time() default 60; // 时间窗口(秒)
- RateLimitType type() default RateLimitType.IP;
- }
- public enum RateLimitType {
- IP, // 按IP限制
- USER, // 按用户限制
- METHOD, // 按方法限制
- GLOBAL // 全局限制
- }
- // AOP限流实现
- @Aspect
- @Component
- public class RateLimitAspect {
-
- private final RedisTemplate<String, Object> redisTemplate;
-
- @Around("@annotation(rateLimit)")
- public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {
- String key = generateKey(joinPoint, rateLimit);
-
- if (!tryAcquire(key, rateLimit)) {
- throw new RateLimitExceededException("请求过于频繁");
- }
-
- try {
- return joinPoint.proceed();
- } finally {
- // 清理资源
- }
- }
-
- private boolean tryAcquire(String key, RateLimit rateLimit) {
- String redisKey = "rate_limit:" + key;
- Long count = redisTemplate.opsForValue().increment(redisKey);
-
- if (count == 1) {
- redisTemplate.expire(redisKey, rateLimit.time(), TimeUnit.SECONDS);
- }
-
- return count <= rateLimit.value();
- }
- }
复制代码
【2】请求指纹识别
- @Component
- public class RequestFingerprint {
-
- public String generate(HttpServletRequest request) {
- String fingerprint = String.join("|",
- request.getRemoteAddr(),
- request.getHeader("User-Agent"),
- getBrowserFingerprint(request),
- getDeviceFingerprint(request)
- );
- return DigestUtils.md5DigestAsHex(fingerprint.getBytes());
- }
-
- private String getBrowserFingerprint(HttpServletRequest request) {
- // 基于浏览器特性生成指纹
- return String.join(",",
- request.getHeader("Accept-Language"),
- request.getHeader("Accept-Encoding"),
- request.getHeader("Accept")
- );
- }
- }
复制代码
【3】人机验证集成
- @Service
- public class CaptchaService {
-
- public boolean verifyCaptcha(String captcha, String clientIp) {
- // 1. 基础验证
- if (StringUtils.isEmpty(captcha)) {
- return false;
- }
-
- // 2. 验证码服务调用
- CaptchaResult result = captchaClient.verify(captcha, clientIp);
-
- // 3. 风险评估
- RiskAssessment risk = assessRisk(clientIp, result.getScore());
-
- return risk.isAllowed();
- }
-
- @RateLimit(value = 5, time = 300, type = RateLimitType.IP)
- public String generateCaptcha(String clientIp) {
- // 生成验证码逻辑
- return captchaClient.generate(clientIp);
- }
- }
复制代码
【4】使用Spring Security
- @Configuration
- @EnableWebSecurity
- public class SecurityConfig extends WebSecurityConfigurerAdapter {
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http
- .authorizeRequests()
- .antMatchers("/public/**").permitAll()
- .anyRequest().authenticated()
- .and()
- .addFilterBefore(new RateLimitFilter(), UsernamePasswordAuthenticationFilter.class);
- }
- }
- public class RateLimitFilter extends OncePerRequestFilter {
- private final RateLimiter rateLimiter = RateLimiter.create(100); // 每秒100个请求
- @Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
- if (!rateLimiter.tryAcquire()) {
- response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
- response.getWriter().write("Too many requests");
- return;
- }
- filterChain.doFilter(request, response);
- }
- }
复制代码
【5】数据脱敏
【七】微服务间防护
【1】Feign 客户端防护
- @FeignClient(name = "user-service",
- configuration = FeignSecurityConfig.class,
- fallbackFactory = UserServiceFallbackFactory.class)
- public interface UserServiceClient {
-
- @RateLimit(value = 50, time = 60)
- @GetMapping("/users/{id}")
- ResponseEntity<User> getUser(@PathVariable Long id);
-
- @PostMapping("/users")
- ResponseEntity<User> createUser(@RequestBody User user);
- }
- // Feign配置
- @Configuration
- public class FeignSecurityConfig {
-
- @Bean
- public RequestInterceptor rateLimitInterceptor() {
- return template -> {
- // 添加限流头信息
- template.header("X-RateLimit-Service", "user-service");
- };
- }
-
- @Bean
- public Retryer feignRetryer() {
- // 防止重放攻击,限制重试次数
- return new Retryer.Default(100, 1000, 3);
- }
- }
- // 降级处理
- @Component
- public class UserServiceFallbackFactory implements FallbackFactory<UserServiceClient> {
-
- @Override
- public UserServiceClient create(Throwable cause) {
- return new UserServiceClient() {
- @Override
- public ResponseEntity<User> getUser(Long id) {
- // 记录攻击日志
- log.warn("User service fallback triggered by: {}", cause.getMessage());
- return ResponseEntity.status(503).build();
- }
- };
- }
- }
复制代码
【八】缓存层防护
【1】Redis 缓存击穿防护
- @Service
- public class CacheProtectionService {
-
- public <T> T getWithProtection(String key, Class<T> type,
- Supplier<T> loader, Duration timeout) {
- // 1. 布隆过滤器检查
- if (!bloomFilter.mightContain(key)) {
- return null;
- }
-
- // 2. 缓存获取
- T value = redisTemplate.opsForValue().get(key);
- if (value != null) {
- return value;
- }
-
- // 3. 分布式锁防止缓存击穿
- String lockKey = "lock:" + key;
- boolean locked = tryLock(lockKey, timeout);
- if (!locked) {
- // 等待其他线程加载
- return waitForCache(key, type, timeout);
- }
-
- try {
- // 双重检查
- value = redisTemplate.opsForValue().get(key);
- if (value != null) {
- return value;
- }
-
- // 加载数据
- value = loader.get();
- if (value != null) {
- redisTemplate.opsForValue().set(key, value, timeout);
- bloomFilter.put(key); // 更新布隆过滤器
- }
-
- return value;
- } finally {
- releaseLock(lockKey);
- }
- }
- }
复制代码
【2】热点数据保护
- @Component
- public class HotKeyProtection {
-
- private final Map<String, AtomicLong> accessCounters = new ConcurrentHashMap<>();
- private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
-
- @PostConstruct
- public void init() {
- // 定期清理计数器
- scheduler.scheduleAtFixedRate(this::cleanupCounters, 1, 1, TimeUnit.MINUTES);
- }
-
- public boolean isHotKey(String key) {
- AtomicLong counter = accessCounters.computeIfAbsent(key, k -> new AtomicLong());
- long count = counter.incrementAndGet();
-
- // 阈值判断
- return count > 1000; // 每分钟超过1000次访问
- }
-
- public void handleHotKey(String key, Runnable fallback) {
- if (isHotKey(key)) {
- // 热点Key降级处理
- fallback.run();
- log.warn("Hot key detected: {}", key);
- }
- }
- }
复制代码
【八】监控与告警体系
【1】Micrometer 监控指标
- @Component
- public class DdosMetrics {
-
- private final MeterRegistry meterRegistry;
- private final Counter requestCounter;
- private final DistributionSummary requestSizeSummary;
-
- public DdosMetrics(MeterRegistry meterRegistry) {
- this.meterRegistry = meterRegistry;
- this.requestCounter = Counter.builder("http.requests")
- .tag("type", "ddos_protection")
- .register(meterRegistry);
-
- this.requestSizeSummary = DistributionSummary.builder("http.request.size")
- .register(meterRegistry);
- }
-
- public void recordRequest(HttpServletRequest request, boolean blocked) {
- requestCounter.increment();
-
- if (blocked) {
- meterRegistry.counter("http.requests.blocked").increment();
- }
-
- // 记录请求大小
- int contentLength = request.getContentLength();
- if (contentLength > 0) {
- requestSizeSummary.record(contentLength);
- }
-
- // 记录IP频率
- String ip = request.getRemoteAddr();
- meterRegistry.counter("ip.requests", "ip", ip).increment();
- }
- }
复制代码
【2】自定义健康检查
- @Component
- public class DdosHealthIndicator implements HealthIndicator {
-
- private final RedisTemplate<String, String> redisTemplate;
-
- @Override
- public Health health() {
- Map<String, Object> details = new HashMap<>();
-
- // 检查请求频率
- long totalRequests = getTotalRequestsLastMinute();
- details.put("totalRequestsLastMinute", totalRequests);
-
- // 检查阻塞请求数
- long blockedRequests = getBlockedRequestsLastMinute();
- details.put("blockedRequestsLastMinute", blockedRequests);
-
- // 风险评估
- if (totalRequests > 10000 || blockedRequests > 1000) {
- return Health.down()
- .withDetails(details)
- .withDetail("error", "Possible DDoS attack detected")
- .build();
- }
-
- return Health.up().withDetails(details).build();
- }
- }
复制代码
【3】告警规则配置
- # Prometheus告警规则
- groups:
- - name: ddos_alerts
- rules:
- - alert: HighRequestRate
- expr: rate(http_requests_total[5m]) > 1000
- for: 2m
- labels:
- severity: critical
- annotations:
- summary: "高请求率告警"
- description: "当前请求率: {{ $value }} req/s"
-
- - alert: ManyBlockedRequests
- expr: rate(http_requests_blocked_total[5m]) > 100
- for: 5m
- labels:
- severity: warning
- annotations:
- summary: "大量请求被拦截"
-
- - alert: SuspiciousIP
- expr: sum by (ip) (rate(ip_requests_total[1m])) > 500
- for: 1m
- labels:
- severity: critical
复制代码
【4】使用Spring Boot Actuator
(1)应用健康检查
实时暴露应用健康状态(数据库、磁盘、服务依赖等)
- // 访问 /actuator/health 返回示例
- {
- "status": "UP",
- "components": {
- "db": { "status": "UP", "details": { "database": "H2" } },
- "diskSpace": { "status": "UP", "details": { "free": 100GB } }
- }
- }
复制代码
(2)指标监控
集成 Micrometer 收集 JVM/HTTP/缓存等 500+ 指标
(3)运行时洞察
动态查看日志级别、线程堆栈、环境变量等
(4)审计跟踪
记录用户操作事件(登录、数据修改等)
- @Bean
- public AuditEventRepository auditEventRepository() {
- return new InMemoryAuditEventRepository(); // 可替换为JDBC实现
- }
复制代码
(5)优雅停机
确保服务关闭时不中断进行中的请求
- server:
- shutdown: graceful # 开启优雅停机
- spring:
- lifecycle:
- timeout-per-shutdown-phase: 30s # 最长等待时间
复制代码
【九】应急响应机制
【1】自动封禁策略
- @Service
- public class AutoBlockService {
-
- @Scheduled(fixedRate = 60000) // 每分钟检查
- public void autoBlockMaliciousIps() {
- Map<String, Long> ipStats = getIpRequestStats();
-
- ipStats.entrySet().stream()
- .filter(entry -> entry.getValue() > 1000) // 每分钟超过1000次
- .forEach(entry -> {
- String ip = entry.getKey();
- blockIp(ip, Duration.ofHours(1)); // 封禁1小时
- log.warn("Auto blocked IP: {} for excessive requests: {}", ip, entry.getValue());
-
- // 发送告警
- alertService.sendAlert("IP自动封禁",
- "IP: " + ip + " 请求数: " + entry.getValue());
- });
- }
-
- public void blockIp(String ip, Duration duration) {
- String key = "blocked_ip:" + ip;
- redisTemplate.opsForValue().set(key, "1", duration);
- }
- }
复制代码
【2】降级策略
- @Component
- public class DegradationStrategy {
-
- public void activateEmergencyMode() {
- // 1. 关闭非核心服务
- feignConfig.disableNonCriticalServices();
-
- // 2. 启用静态降级页面
- staticModeService.enable();
-
- // 3. 限制API速率
- rateLimitConfig.setStrictMode(true);
-
- // 4. 发送通知
- notificationService.sendEmergencyAlert("DDoS攻击防护已激活");
- }
-
- @EventListener
- public void handleDdosEvent(DdosDetectedEvent event) {
- if (event.getSeverity() == Severity.CRITICAL) {
- activateEmergencyMode();
- }
- }
- }
复制代码
【十】测试与演练
【1】压力测试配置
- @SpringBootTest
- @TestPropertySource(properties = {
- "spring.redis.embedded=true",
- "resilience4j.ratelimiter.enabled=true"
- })
- public class DdosProtectionTest {
-
- @Autowired
- private TestRestTemplate restTemplate;
-
- @Test
- public void testRateLimiting() {
- // 模拟高并发请求
- List<CompletableFuture<ResponseEntity<String>>> futures = new ArrayList<>();
-
- for (int i = 0; i < 1000; i++) {
- futures.add(CompletableFuture.supplyAsync(() ->
- restTemplate.getForEntity("/api/users/1", String.class)
- ));
- }
-
- // 统计429响应数量
- long blockedCount = futures.stream()
- .map(CompletableFuture::join)
- .filter(response -> response.getStatusCode() == HttpStatus.TOO_MANY_REQUESTS)
- .count();
-
- assertThat(blockedCount).isGreaterThan(800); // 80%请求应被限流
- }
- }
复制代码
【2】混沌工程测试
- @Component
- public class ChaosTestService {
-
- public void simulateDdosAttack() {
- // 1. 生成大量请求
- IntStream.range(0, 10000).parallel().forEach(i -> {
- restTemplate.getForObject("/api/data", String.class);
- });
-
- // 2. 验证防护效果
- Health health = healthEndpoint.health();
- assertThat(health.getStatus()).isEqualTo(Status.UP);
- }
- }
复制代码
【十一】总结
【1】网络层
云防护、防火墙进行DDoS清洗、IP封禁
【2】Nginx流量网管层
【3】Gateway业务网关层
(1)https强制跳转和证书配置
(2)全局过滤器请求限流防护(对服务)
令牌桶限流,例如100-1000,根据业务需求来配置
(3)CORS跨域安全过滤器
1-config.addAllowedOrigin(“https://trusted-domain.com”);
精确指定可信域名,不允许任意源访问
2-config.setExposedHeaders(“Authorization”);
仅暴露必要头信息,用来传token令牌
3-config.addAllowedHeader(List.of(“Content-Type”,“Accept”));
(4)sql注入检查和XSS攻击过滤器
sql注入检查
攻击者通过在应用程序的输入字段中插入恶意的SQL代码,从而欺骗数据库执行非法的SQL命令。这可能导致数据泄露、数据篡改、甚至数据库服务器被完全控制。
1-检查请求参数(包括查询参数、请求体、路径变量等)中是否包含可疑的SQL关键字或特殊字符。
2-使用正则表达式或字符串匹配来检测常见的SQL注入模式。
复杂的SQL注入攻击可能使用编码、注释等方式绕过简单的关键字匹配。因此,网关层的SQL注入防护通常作为一道基础防线,更深入的防护应该在应用层(如使用预编译语句、ORM框架等)实现。
检查XSS攻击
XSS(跨站脚本攻击)是一种常见的网络安全漏洞,攻击者通过在网页中注入恶意脚本,当其他用户浏览该网页时,脚本执行,从而窃取用户信息、会话令牌或进行其他恶意操作。
1-检查输入中是否包含可疑的HTML标签(如
(5)JWT认证过滤器
1-使用非对称加密(RS256),秘钥公钥分离,秘钥做好安全存放
2-使用强密钥,定期轮换密钥(通过JWKS端点)
3-防止令牌泄露:强制HTTPS,设置HttpOnly Cookie
4-限制令牌有效期:设置合理的exp时间(通常30分钟-2小时)
5-敏感操作要求重新认证
6-添加必要的安全头Authorization
7-结合API网关的限流功能防止暴力破解
8-令牌token里不要放敏感信息
(6)IP黑白名单控制
(7)敏感头信息过滤
(8)请求大小限制
(9)OAuth2资源服务器配置
1-有些高密的接口配置高级访问权限的限制
【4】应用层
(1)人机验证
1-登录或者注册接口,使用输入编码或点击图片等实现人机验证和机器人过滤
(2)token令牌
1-登录成功后,通过秘钥生成token令牌,设置令牌的过期时间,返回给前端放进cookie,下次请求带token
2-请求达到gateway会经过SpringSecurity的过滤器,对token进行解密和校验,如果token不存在或者已过期,则跳转到登录页面
(3)业务限流
1-根据业务的实际情况对某些接口进行限流,例如登录注册接口和其他业务接口,使用不同的限流配置
(4)服务监控报警
1-自定义健康检查
(5)自动封禁和降级
1-对于访问频率异常的ip可以放进redis黑名单缓存里1小时,gateway黑名单过滤的时候进行过滤
(6)人工干预降级
(7)数据脱敏存储
【5】服务层
(1)Hystrix熔断降级
(2)Feign容错
(3)传递token校验
【6】Redis、布隆过滤器
热点保护、击穿防护
使用道具 举报