如何修复Java Spring Boot应用中的‘Cookie Security: Cookie not Sent Over SSL (4720)’漏洞
一、修复‘Cookie not Sent Over SSL (4720)’漏洞
这个漏洞的核心原因是Cookie未设置Secure属性,导致Cookie可能通过HTTP明文传输。以下是代码/配置层面的修复方式:
1. 配置文件方式(application.properties/yaml)
直接在配置文件中全局设置Session Cookie的安全属性:
# 开启Secure属性,仅允许Cookie通过HTTPS传输 server.servlet.session.cookie.secure=true # 附加安全配置:禁止JS读取Cookie,降低XSS风险 server.servlet.session.cookie.http-only=true # 限制Cookie跨站发送,防范CSRF攻击 server.servlet.session.cookie.same-site=Strict
2. Java配置类方式
如果需要更灵活的控制,可通过配置类设置Session Cookie属性:
import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.servlet.SessionCookieConfig; import javax.servlet.ServletContext; @Configuration public class CookieSecurityConfig { @Bean public ServletContextInitializer servletContextInitializer() { return servletContext -> { SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig(); sessionCookieConfig.setSecure(true); // 强制仅HTTPS传输Cookie sessionCookieConfig.setHttpOnly(true); sessionCookieConfig.setSameSite("Strict"); }; } }
3. 自定义Cookie的处理
如果是业务代码中手动创建的自定义Cookie,必须显式设置Secure属性:
import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; public void setCustomCookie(HttpServletResponse response) { Cookie customCookie = new Cookie("business-token", "user-specific-value"); customCookie.setSecure(true); // 关键:开启Secure属性 customCookie.setHttpOnly(true); customCookie.setSameSite("Strict"); customCookie.setPath("/"); // 根据业务需求设置路径 response.addCookie(customCookie); }
二、Cookie加密实现及解密说明
Spring Boot框架本身不会自动加密Cookie,需要手动实现或借助Spring Security的工具类完成:
1. Session Cookie加密(基于Spring Security)
如果是Spring Security管理的Session Cookie,可通过自定义CookieSerializer实现加密:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.web.savedrequest.DefaultCookieSerializer; @Configuration public class SecurityCookieConfig { @Bean public DefaultCookieSerializer cookieSerializer() { DefaultCookieSerializer serializer = new DefaultCookieSerializer(); serializer.setSecure(true); serializer.setHttpOnly(true); serializer.setSameSite("Strict"); serializer.setCookieName("SESSION"); serializer.setDomainName("your-domain.com"); // 替换为实际域名 // 设置加密密钥(建议从环境变量/配置中心读取,避免硬编码) serializer.setCookieCipherKey("your-256-bit-secret-key".getBytes()); // 密钥需为16/24/32字节(对应AES-128/192/256) return serializer; } }
这种方式下,Spring Security会自动完成Session Cookie的加密和解密,无需手动处理。
2. 自定义Cookie加密
对于业务自定义的Cookie,需手动实现加密解密逻辑:
加密工具类
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class CookieCryptoUtil { private static final String AES_ALGORITHM = "AES"; // 建议从环境变量读取密钥,密钥长度必须为16/24/32字节 private static final String SECRET_KEY = System.getenv("COOKIE_ENCRYPT_KEY"); // 加密Cookie值 public static String encrypt(String plainValue) throws Exception { SecretKeySpec keySpec = new SecretKeySpec(SECRET_KEY.getBytes(), AES_ALGORITHM); Cipher cipher = Cipher.getInstance(AES_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, keySpec); byte[] encryptedBytes = cipher.doFinal(plainValue.getBytes()); return Base64.getEncoder().encodeToString(encryptedBytes); } // 解密Cookie值 public static String decrypt(String encryptedValue) throws Exception { SecretKeySpec keySpec = new SecretKeySpec(SECRET_KEY.getBytes(), AES_ALGORITHM); Cipher cipher = Cipher.getInstance(AES_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, keySpec); byte[] decodedBytes = Base64.getDecoder().decode(encryptedValue); byte[] decryptedBytes = cipher.doFinal(decodedBytes); return new String(decryptedBytes); } }
设置加密Cookie
import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; public void setEncryptedBusinessCookie(HttpServletResponse response) throws Exception { String sensitiveData = "user-sensitive-info"; String encryptedData = CookieCryptoUtil.encrypt(sensitiveData); Cookie encryptedCookie = new Cookie("sensitive-cookie", encryptedData); encryptedCookie.setSecure(true); encryptedCookie.setHttpOnly(true); encryptedCookie.setSameSite("Strict"); encryptedCookie.setPath("/"); response.addCookie(encryptedCookie); }
读取并解密Cookie
import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; public String getDecryptedBusinessCookie(HttpServletRequest request) throws Exception { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if ("sensitive-cookie".equals(cookie.getName())) { return CookieCryptoUtil.decrypt(cookie.getValue()); } } } return null; }
解密是否自动处理?
- Session Cookie:使用Spring Security的
CookieSerializer配置加密后,框架会自动完成解密,无需手动干预。 - 自定义Cookie:框架不会自动处理,必须在读取Cookie时手动调用解密方法。
内容的提问来源于stack exchange,提问作者Jake Turner
相关产品推荐
相关产品推荐

