【系统安全】DDoS攻击
- 【一】什么是DDoS攻击
- [【二】DDoS 攻击类型与防护架构](#【二】DDoS 攻击类型与防护架构)
- 【三】基础设施层防护
-
- 【1】云服务商防护配置
- [【2】CDN 动态加速配置](#【2】CDN 动态加速配置)
- 【四】Nginx流量网关
- [【五】API 网关层防护(Spring Cloud Gateway)](#【五】API 网关层防护(Spring Cloud Gateway))
- [【六】应用层防护(Spring Boot)](#【六】应用层防护(Spring Boot))
-
- 【1】自定义限流注解:对接口限流
- 【2】请求指纹识别
- 【3】人机验证集成
- [【4】使用Spring Security](#【4】使用Spring Security)
- 【5】数据脱敏
- 【七】微服务间防护
-
- [【1】Feign 客户端防护](#【1】Feign 客户端防护)
- 【八】缓存层防护
-
- [【1】Redis 缓存击穿防护](#【1】Redis 缓存击穿防护)
- 【2】热点数据保护
- 【八】监控与告警体系
-
- [【1】Micrometer 监控指标](#【1】Micrometer 监控指标)
- 【2】自定义健康检查
- 【3】告警规则配置
- [【4】使用Spring Boot Actuator](#【4】使用Spring Boot Actuator)
- 【九】应急响应机制
- 【十】测试与演练
- 【十一】总结
【一】什么是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】云服务商防护配置
yml
# 阿里云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 动态加速配置
java
@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】限流配置:对服务限流
对服务配置限流
yml
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】自定义限流策略
java
@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)请求频率检查
java
@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强制跳转与证书配置
yml
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"));
java
@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令牌桶)
yml
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}"
java
@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:用户信息
指定了七个默认字段供选择
也可以自定义私有字段,但是不建议在此存放密码之类的敏感信息,因为此部分可以解码还原出原始内容。虽然它可以解码,但是也不能修改这个内容。
java
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,得到用户信息、头信息等,根据用户信息查询到对应库里的用户信息,然后用同样的加密算法加密,然后判断加密后的信息是否一致
java
@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黑白名单控制
yml
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)敏感头信息过滤
yml
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)请求大小限制
yml
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标签(如
java
@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资源服务器配置
yml
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://auth-server.com
jwk-set-uri: https://auth-server.com/.well-known/jwks.json
java
@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】自定义限流注解:对接口限流
java
@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】请求指纹识别
java
@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】人机验证集成
java
@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
java
@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 客户端防护
java
@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 缓存击穿防护
java
@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】热点数据保护
java
@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 监控指标
java
@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】自定义健康检查
java
@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】告警规则配置
yml
# 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)应用健康检查
实时暴露应用健康状态(数据库、磁盘、服务依赖等)
json
// 访问 /actuator/health 返回示例
{
"status": "UP",
"components": {
"db": { "status": "UP", "details": { "database": "H2" } },
"diskSpace": { "status": "UP", "details": { "free": 100GB } }
}
}
(2)指标监控
集成 Micrometer 收集 JVM/HTTP/缓存等 500+ 指标
(3)运行时洞察
动态查看日志级别、线程堆栈、环境变量等
(4)审计跟踪
记录用户操作事件(登录、数据修改等)
java
@Bean
public AuditEventRepository auditEventRepository() {
return new InMemoryAuditEventRepository(); // 可替换为JDBC实现
}
(5)优雅停机
确保服务关闭时不中断进行中的请求
yml
server:
shutdown: graceful # 开启优雅停机
spring:
lifecycle:
timeout-per-shutdown-phase: 30s # 最长等待时间
【九】应急响应机制
【1】自动封禁策略
java
@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】降级策略
java
@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】压力测试配置
java
@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】混沌工程测试
java
@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、布隆过滤器
热点保护、击穿防护