蓝布编程网

分享编程技术文章,编程语言教程与实战经验

Java接口安全:SpringBoot防护XSS/SQL/重放攻击

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)
  }
})

防护体系增强建议

  1. 深度防御
  2. 结合Spring Security进行权限控制
  3. 使用@Validated进行输入验证
  4. 启用HTTPS防止中间人攻击
  5. 日志监控

java

@Aspect
@Component
public class SecurityLogger {
    @AfterThrowing(pointcut = "execution(* com.example..*.*(..))", throwing = "ex")
    public void logSecurityException(SecurityException ex) {
        log.error("Security alert: {}", ex.getMessage());
        // 发送告警通知
    }
}
  1. 定期更新
  2. 保持Spring Boot和依赖库最新版本
  3. 使用OWASP Dependency-Check检查漏洞

关键原则:所有外部输入皆不可信!必须经过验证/过滤/转义处理。三种攻击组合防护可覆盖Web应用80%的安全风险,但需根据业务场景持续调整策略。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言