API安全设计与防护实战
API安全设计与防护实战一、API安全概述API作为系统间交互的接口是攻击的主要目标。一个安全的API设计需要考虑多个层面的防护包括认证、授权、数据保护、攻击防护等。二、API认证机制2.1 API Key认证Component public class ApiKeyFilter extends OncePerRequestFilter { private static final String API_KEY_HEADER X-API-Key; private static final String VALID_API_KEY your-api-key-here; Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String apiKey request.getHeader(API_KEY_HEADER); if (!VALID_API_KEY.equals(apiKey)) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.getWriter().write(Unauthorized: Invalid API Key); return; } filterChain.doFilter(request, response); } }2.2 基于证书的双向认证server: ssl: enabled: true key-store: classpath:server.jks key-store-password: password trust-store: classpath:truststore.jks trust-store-password: password client-auth: need三、API授权策略3.1 RBAC基于角色的访问控制Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers(/api/admin/**).hasRole(ADMIN) .antMatchers(/api/user/**).hasRole(USER) .antMatchers(/api/public/**).permitAll() .anyRequest().authenticated(); } }3.2 ABAC基于属性的访问控制Component public class AbacAuthorizationManager { public boolean isAllowed(User user, Resource resource, Action action) { // 根据用户属性、资源属性、环境属性进行动态授权判断 if (admin.equals(user.getRole())) { return true; } if (read.equals(action) resource.isPublic()) { return true; } if (resource.getOwnerId().equals(user.getId())) { return true; } return false; } }四、输入验证与数据保护4.1 参数校验RestController RequestMapping(/api/users) public class UserController { PostMapping public ResponseEntityUser createUser(Valid RequestBody UserCreateRequest request) { // 参数已通过Valid注解自动校验 User user userService.createUser(request); return ResponseEntity.ok(user); } } public class UserCreateRequest { NotBlank(message 用户名不能为空) Size(min 3, max 50, message 用户名长度必须在3-50之间) private String username; Email(message 邮箱格式不正确) NotBlank(message 邮箱不能为空) private String email; NotBlank(message 密码不能为空) Size(min 8, message 密码长度至少8位) private String password; }4.2 SQL注入防护错误写法// 存在SQL注入风险 String sql SELECT * FROM users WHERE username username ;正确写法// 使用预编译语句 String sql SELECT * FROM users WHERE username ?; PreparedStatement stmt connection.prepareStatement(sql); stmt.setString(1, username); ResultSet rs stmt.executeQuery();4.3 XSS攻击防护import org.jsoup.Jsoup; import org.jsoup.safety.Safelist; public class XssUtils { public static String clean(String input) { if (input null) { return null; } return Jsoup.clean(input, Safelist.relaxed()); } }五、API限流与熔断5.1 使用Bucket4j进行限流Configuration public class RateLimitConfig { Bean public Bucket bucket() { Refill refill Refill.greedy(100, Duration.ofMinutes(1)); Bandwidth limit Bandwidth.classic(100, refill); return Bucket.builder().addLimit(limit).build(); } } Component public class RateLimitFilter extends OncePerRequestFilter { Autowired private Bucket bucket; Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (bucket.tryConsume(1)) { filterChain.doFilter(request, response); } else { response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS); response.getWriter().write(Rate limit exceeded); } } }5.2 Hystrix熔断配置Configuration public class HystrixConfig { Bean public HystrixCommand.Setter defaultCommandProperties() { return HystrixCommand.Setter .withGroupKey(HystrixCommandGroupKey.Factory.asKey(DefaultGroup)) .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() .withExecutionTimeoutInMilliseconds(5000) .withCircuitBreakerRequestVolumeThreshold(20) .withCircuitBreakerErrorThresholdPercentage(50) .withCircuitBreakerSleepWindowInMilliseconds(30000)); } }六、安全审计与日志6.1 审计日志记录Aspect Component public class AuditAspect { Autowired private AuditLogRepository auditLogRepository; Around(annotation(auditable)) public Object audit(ProceedingJoinPoint joinPoint, Auditable auditable) throws Throwable { AuditLog log new AuditLog(); log.setAction(auditable.action()); log.setResource(auditable.resource()); log.setTimestamp(LocalDateTime.now()); try { Object result joinPoint.proceed(); log.setStatus(SUCCESS); return result; } catch (Exception e) { log.setStatus(FAILED); log.setErrorMessage(e.getMessage()); throw e; } finally { auditLogRepository.save(log); } } } Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface Auditable { String action(); String resource(); }6.2 安全日志脱敏public class LogSanitizer { private static final Pattern EMAIL_PATTERN Pattern.compile([a-zA-Z0-9._%-][a-zA-Z0-9.-]\\.[a-zA-Z]{2,}); private static final Pattern PHONE_PATTERN Pattern.compile(1[3-9]\\d{9}); private static final Pattern CARD_PATTERN Pattern.compile(\\d{4}\\s*\\d{4}\\s*\\d{4}\\s*\\d{4}); public static String sanitize(String message) { if (message null) { return null; } String sanitized EMAIL_PATTERN.matcher(message).replaceAll(******.com); sanitized PHONE_PATTERN.matcher(sanitized).replaceAll(1*** **** ****); sanitized CARD_PATTERN.matcher(sanitized).replaceAll(**** **** **** ****); return sanitized; } }七、API安全测试7.1 使用OWASP ZAP进行安全扫描# 启动ZAP代理 zap.sh -daemon -port 8080 -config scanner.maxRuleDurationInMins5 # 运行主动扫描 curl -X POST http://localhost:8080/JSON/ascan/action/scan \ -d {apikey:your-api-key,url:http://localhost:8080/api,recurse:true} # 获取扫描结果 curl http://localhost:8080/JSON/ascan/view/alerts \ -d {apikey:your-api-key,baseurl:http://localhost:8080/api}7.2 安全测试清单认证测试 - [ ] 无Token访问受限API - [ ] 使用过期Token访问 - [ ] 使用无效Token访问 - [ ] Token劫持测试 授权测试 - [ ] 越权访问其他用户数据 - [ ] 普通用户访问管理员接口 - [ ] 未授权访问敏感资源 输入验证测试 - [ ] SQL注入测试 - [ ] XSS攻击测试 - [ ] 参数边界值测试 - [ ] 恶意文件上传测试 安全配置测试 - [ ] HTTPS强制测试 - [ ] CORS配置验证 - [ ] 敏感信息泄露检查 - [ ] 错误信息泄露检查八、总结API安全是一个系统性工程需要从认证授权、输入验证、限流熔断、审计日志等多个维度进行防护。通过采用业界成熟的安全框架和最佳实践可以有效降低API被攻击的风险。同时定期进行安全测试和漏洞扫描及时修复发现的安全问题是保障API安全的重要环节。参考资料OWASP API Security Top 10: https://github.com/OWASP/API-SecuritySpring Security Documentation: https://spring.io/projects/spring-securityBucket4j: https://bucket4j.com/