Table of Contents
Spring Boot : API 접속 건수 제한하기
DDOS 공격에 대비하기 위해, 일정 접속 건수 이상의 API 호출을 제한한다.
의존성 추가
dependencies {
// ......
implementation("com.bucket4j:bucket4j-core:8.6.0")
}
서비스
@Service
@RequiredArgsConstructor
public class RateLimitService {
private final Map<String, Bucket> cache = new ConcurrentHashMap<>();
public boolean allowRequest(String key) {
Bucket bucket = cache.computeIfAbsent(key, k -> {
// 아이피당 분당 20회 제한
Bandwidth limit = Bandwidth.builder()
.capacity(20)
.refillIntervally(20, Duration.ofMinutes(1))
.build();
return Bucket.builder()
.addLimit(limit)
.build();
});
return bucket.tryConsume(1);
}
}
컨트롤러
@PostMapping("/myApi")
public ResponseEntity<?> myApi(@Valid @RequestBody MyApiRequest request, HttpServletRequest httpRequest) {
String clientKey = getClientIpAddress(httpRequest);
if (!rateLimitService.allowRequest("refresh:" + clientKey)) {
throw new TooManyAccessException("너무 많은 요청입니다. 잠시 후 다시 시도해주세요.");
}
// ......
}
private String getClientIpAddress(HttpServletRequest request) {
String xForwardedFor = request.getHeader("X-Forwarded-For");
if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
return xForwardedFor.split(",")[0].trim();
}
String xRealIp = request.getHeader("X-Real-IP");
if (xRealIp != null && !xRealIp.isEmpty()) {
return xRealIp;
}
return request.getRemoteAddr();
}