Java接口安全:SpringBoot防护XSS/SQL/重放攻击
在Spring Boot中防护XSS、SQL注入和重放攻击是保障应用安全的关键环节。以下是针对这三类攻击的防护策略及具体Java代码实现:
1. XSS攻击防护
攻击原理:恶意脚本注入到网页,在用户浏览器执行
防护方案:输入过滤 + 输出转义
代码实现:
java
// 方案1:全局XSS过滤器 (基于Servlet Filter)
@Component
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
// 使用包装器对请求参数进行清洗
chain.doFilter(new XssRequestWrapper(request), res);
}
}
// XSS请求包装器
public class XssRequestWrapper extends HttpServletRequestWrapper {
private static final HtmlSanitizer SANITIZER = new HtmlSanitizer(); // 自定义消毒器
public XssRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
return sanitize(value); // 参数消毒
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null) return null;
return Arrays.stream(values).map(this::sanitize).toArray(String[]::new);
}
private String sanitize(String input) {
// 使用JSoup或自定义规则过滤HTML标签
return SANITIZER.sanitize(input);
}
}
// 简单HTML消毒器实现
public class HtmlSanitizer {
public String sanitize(String input) {
if (input == null) return null;
// 使用JSoup白名单过滤
Whitelist whitelist = Whitelist.basicWithImages();
return Jsoup.clean(input, whitelist);
}
}
增强措施:
- 响应头防护:强制浏览器启用XSS防护
java
@Configuration
public class SecurityConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.addHeaderWriter((request, response) -> {
response.setHeader("X-XSS-Protection", "1; mode=block");
response.setHeader("Content-Security-Policy", "default-src 'self'");
});
}
}
2. SQL注入防护
攻击原理:通过拼接恶意SQL破坏数据库操作
防护方案:参数化查询 + ORM框架
代码实现:
java
// 方案1:使用JPA/Hibernate (自动参数化)
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// 安全:自动使用预编译语句
@Query("SELECT u FROM User u WHERE u.username = :username")
User findByUsername(@Param("username") String username);
}
// 方案2:JdbcTemplate参数化查询
@Repository
public class UserDao {
private final JdbcTemplate jdbcTemplate;
public User findUser(String username) {
String sql = "SELECT * FROM users WHERE username = ?"; // 使用?占位符
return jdbcTemplate.queryForObject(sql, new Object[]{username}, userMapper);
}
}
禁止做法(高危!):
java
// 错误示例:直接拼接SQL
String sql = "SELECT * FROM users WHERE username='" + username + "'";
jdbcTemplate.execute(sql); // 存在SQL注入漏洞
3. 重放攻击防护
攻击原理:恶意重复发送合法请求
防护方案:Nonce + 时间戳 + 签名
代码实现:
java
// 重放攻击拦截器
@Component
public class ReplayAttackInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final long MAX_TIME_DIFF = 5 * 60 * 1000; // 5分钟有效期
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String nonce = request.getHeader("X-Nonce");
String timestamp = request.getHeader("X-Timestamp");
String signature = request.getHeader("X-Signature");
// 1. 检查必要头是否存在
if (StringUtils.isEmpty(nonce) || ... ) {
throw new SecurityException("Missing security headers");
}
// 2. 验证时间戳有效性
long currentTime = System.currentTimeMillis();
if (Math.abs(currentTime - Long.parseLong(timestamp)) > MAX_TIME_DIFF) {
throw new SecurityException("Timestamp expired");
}
// 3. 检查Nonce唯一性
if (redisTemplate.hasKey(nonce)) {
throw new SecurityException("Duplicate request detected");
} else {
redisTemplate.opsForValue().set(nonce, "used", MAX_TIME_DIFF, TimeUnit.MILLISECONDS);
}
// 4. 验证请求签名(示例)
String serverSign = calculateSignature(request, nonce, timestamp);
if (!serverSign.equals(signature)) {
throw new SecurityException("Invalid signature");
}
return true;
}
private String calculateSignature(HttpServletRequest request, String nonce, String timestamp) {
String data = request.getMethod() + request.getRequestURI() + nonce + timestamp;
return DigestUtils.sha256Hex(data + SECRET_KEY); // 使用密钥生成签名
}
}
客户端配合:
javascript
// 前端发送请求时需生成安全头
fetch("/api/payment", {
headers: {
"X-Nonce": generateUUID(), // 唯一随机数
"X-Timestamp": Date.now(),
"X-Signature": sha256(method + url + nonce + timestamp + secretKey)
}
})
防护体系增强建议
- 深度防御:
- 结合Spring Security进行权限控制
- 使用@Validated进行输入验证
- 启用HTTPS防止中间人攻击
- 日志监控:
java
@Aspect
@Component
public class SecurityLogger {
@AfterThrowing(pointcut = "execution(* com.example..*.*(..))", throwing = "ex")
public void logSecurityException(SecurityException ex) {
log.error("Security alert: {}", ex.getMessage());
// 发送告警通知
}
}
- 定期更新:
- 保持Spring Boot和依赖库最新版本
- 使用OWASP Dependency-Check检查漏洞
关键原则:所有外部输入皆不可信!必须经过验证/过滤/转义处理。三种攻击组合防护可覆盖Web应用80%的安全风险,但需根据业务场景持续调整策略。