在Java Spring Boot專案中,防止介面盜刷(即防止惡意使用者或指令碼頻繁呼叫介面)是一個重要的安全措施。以下是幾種優雅的實作方式:
logo
1. 使用限流(Rate Limiting)
限流是一種常見的防止介面盜刷的方法,可以限制某個時間段內對特定介面的請求次數。
使用Spring Cloud Gateway
如果你使用的是Spring Cloud Gateway,可以很方便地整合限流功能。
限流之Spring Cloud Gateway
@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("limit_route", r -> r.path("/api/**") .filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(myRateLimiter()))) .uri("http://example.com")) .build();}@Beanpublic RateLimiter myRateLimiter() { return new RedisRateLimiter(10, 20); // 每秒最多10個請求,每分鐘最多20個請求}
使用Bucket4j
Bucket4j是一個基於令牌桶演算法的Java限流庫,可以很容易地整合到Spring Boot專案中。
令牌桶限流
@Configurationpublic class RateLimitConfig { @Bean public Bucket createBucket() { Bandwidth limit = Bandwidth. classic(10, Refill.intervally(10, Duration.ofMinutes(1))); return Bucket4j.builder().addLimit(limit).build(); }}@RestControllerpublic class MyController { private final Bucket bucket; public MyController(Bucket bucket) { this.bucket = bucket; } @GetMapping("/api/resource") public ResponseEntity<String> getResource() { if (bucket.tryConsume(1)) { return ResponseEntity.ok("Resource"); } return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body("Too many requests"); }}
2. 使用驗證碼
對於一些敏感操作,可以要求使用者輸入驗證碼,以防止自動化指令碼頻繁呼叫介面。
驗證碼
使用Google reCAPTCHA
Google reCAPTCHA是一個廣泛使用的驗證碼服務,可以有效防止自動化指令碼。
前端程式碼如下:
<script src="https://www.google.com/recaptcha/api.js" async defer></script><div class="g-recaptcha" data-sitekey="your_site_key"></div>
在後端驗證:
@PostMapping("/submit")public ResponseEntity<String> submit(@RequestParam String recaptchaResponse) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); MultiValueMap<String, String> map = new LinkedMultiValueMap<>(); map.add("secret", "your_secret_key"); map.add("response", recaptchaResponse); HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers); ResponseEntity<String> response = restTemplate.postForEntity("https://www.google.com/recaptcha/api/siteverify", request, String. class); if (response.getStatusCode() == HttpStatus.OK) { // 驗證成功 } else { // 驗證失敗 } return response;}
3. 使用JWT(JSON Web Token)
JWT可以用於驗證請求的合法性,防止未授權的請求。
生成和驗證JWT
可以使用JJWT庫來生成和驗證JWT。
鑒權之JWT
@Configurationpublic class JwtTokenUtil { private String secret = "your_secret_key"; public String generateToken(String username) { return Jwts.builder() .setSubject(username) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10小時 .signWith(SignatureAlgorithm.HS512, secret) .compact(); } public Boolean validateToken(String token, UserDetails userDetails) { final String username = getUsernameFromToken(token); return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); } private String getUsernameFromToken(String token) { return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject(); } private Boolean isTokenExpired(String token) { final Date expiration = getExpirationDateFromToken(token); return expiration.before(new Date()); } private Date getExpirationDateFromToken(String token) { return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getExpiration(); }}
4. 使用IP黑名單
可以將惡意IP加入黑名單,禁止其存取介面。
程式碼實作IP黑名單
使用Spring Security
可以在Spring Security配置中添加IP黑名單。
@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/api/**").access("not (hasIpAddress('192.168.1.1') or hasIpAddress('192.168.1.2'))") .anyRequest().authenticated(); }}
總結
以上幾種方法可以單獨使用,也可以組合使用,以提高介面的安全性。限流和驗證碼是比較通用的方法,而JWT和IP黑名單則更適合特定場景。根據具體需求選擇合適的方法,可以有效防止介面盜刷。