本文目录导读:

我来为您详细介绍Java中HSTS(HTTP Strict Transport Security)的实现案例。
什么是HSTS
HSTS是一种安全机制,强制浏览器只能通过HTTPS访问网站,防止中间人攻击和SSL剥离攻击。
实现方式
在Servlet Filter中实现
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HSTSFilter implements Filter {
// HSTS配置参数
private static final long MAX_AGE = 31536000L; // 1年
private static final boolean INCLUDE_SUBDOMAINS = true;
private static final boolean PRELOAD = false;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化配置
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 只在HTTPS请求时添加HSTS头
if (httpRequest.isSecure()) {
StringBuilder hstsValue = new StringBuilder();
hstsValue.append("max-age=").append(MAX_AGE);
if (INCLUDE_SUBDOMAINS) {
hstsValue.append("; includeSubDomains");
}
if (PRELOAD) {
hstsValue.append("; preload");
}
httpResponse.setHeader("Strict-Transport-Security", hstsValue.toString());
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
// 清理资源
}
}
Spring Boot配置方式
使用配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requiresChannel()
.anyRequest().requiresSecure() // 强制HTTPS
.and()
.headers()
.httpStrictTransportSecurity()
.includeSubDomains(true)
.maxAgeInSeconds(31536000)
.preload(false);
}
}
使用Filter注册
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HSTSConfiguration {
@Bean
public FilterRegistrationBean<HSTSFilter> hstsFilter() {
FilterRegistrationBean<HSTSFilter> registrationBean =
new FilterRegistrationBean<>();
registrationBean.setFilter(new HSTSFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
return registrationBean;
}
}
完整的HSTS过滤器实现
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.logging.Logger;
@WebFilter("/*")
public class CompleteHSTSFilter implements Filter {
private static final Logger LOGGER =
Logger.getLogger(CompleteHSTSFilter.class.getName());
private HSTSConfig config;
public static class HSTSConfig {
private long maxAge = 31536000; // 1年
private boolean includeSubDomains = true;
private boolean preload = false;
private String[] excludedPaths = new String[]{};
// Getters and setters
public long getMaxAge() { return maxAge; }
public void setMaxAge(long maxAge) { this.maxAge = maxAge; }
public boolean isIncludeSubDomains() { return includeSubDomains; }
public void setIncludeSubDomains(boolean includeSubDomains) {
this.includeSubDomains = includeSubDomains;
}
public boolean isPreload() { return preload; }
public void setPreload(boolean preload) { this.preload = preload; }
public String[] getExcludedPaths() { return excludedPaths; }
public void setExcludedPaths(String[] excludedPaths) {
this.excludedPaths = excludedPaths;
}
}
@Override
public void init(FilterConfig filterConfig) {
this.config = new HSTSConfig();
// 从web.xml或配置读取参数
String maxAge = filterConfig.getInitParameter("maxAge");
if (maxAge != null) {
config.setMaxAge(Long.parseLong(maxAge));
}
String includeSubDomains = filterConfig.getInitParameter("includeSubDomains");
if (includeSubDomains != null) {
config.setIncludeSubDomains(Boolean.parseBoolean(includeSubDomains));
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String requestURI = httpRequest.getRequestURI();
// 检查是否在排除路径中
if (!isExcludedPath(requestURI)) {
// 只在HTTPS请求时添加HSTS头
if (httpRequest.isSecure()) {
String hstsValue = buildHSTSHeader();
httpResponse.setHeader("Strict-Transport-Security", hstsValue);
LOGGER.fine("Added HSTS header to: " + requestURI);
} else {
// 可选:重定向HTTP到HTTPS
String httpsURL = "https://" + httpRequest.getServerName()
+ httpRequest.getRequestURI();
httpResponse.sendRedirect(httpsURL);
return;
}
}
chain.doFilter(request, response);
}
private String buildHSTSHeader() {
StringBuilder hstsValue = new StringBuilder();
hstsValue.append("max-age=").append(config.getMaxAge());
if (config.isIncludeSubDomains()) {
hstsValue.append("; includeSubDomains");
}
if (config.isPreload()) {
hstsValue.append("; preload");
}
return hstsValue.toString();
}
private boolean isExcludedPath(String path) {
for (String excludedPath : config.getExcludedPaths()) {
if (path.startsWith(excludedPath)) {
return true;
}
}
return false;
}
@Override
public void destroy() {
// 清理资源
}
}
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- HSTS Filter -->
<filter>
<filter-name>hstsFilter</filter-name>
<filter-class>com.example.HSTSFilter</filter-class>
<init-param>
<param-name>maxAge</param-name>
<param-value>31536000</param-value>
</init-param>
<init-param>
<param-name>includeSubDomains</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>preload</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hstsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
测试用例
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HSTSFilterTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testHSTSHeaderPresent() throws Exception {
mockMvc.perform(get("/api/test").secure(true))
.andExpect(status().isOk())
.andExpect(header().string("Strict-Transport-Security",
"max-age=31536000; includeSubDomains"));
}
@Test
public void testHSTSHeaderNotOnHTTP() throws Exception {
mockMvc.perform(get("/api/test").secure(false))
.andExpect(status().is3xxRedirection())
.andExpect(header().string("Location").startsWith("https://"));
}
}
最佳实践
配置建议
// 生产环境配置
@Configuration
public class ProductionHSTSConfig {
@Bean
public FilterRegistrationBean<HSTSFilter> hstsFilter() {
FilterRegistrationBean<HSTSFilter> registrationBean =
new FilterRegistrationBean<>();
CompleteHSTSFilter.HSTSConfig config = new CompleteHSTSFilter.HSTSConfig();
config.setMaxAge(63072000); // 2年
config.setIncludeSubDomains(true);
config.setPreload(true);
// 排除不需要HSTS的路径
config.setExcludedPaths(new String[]{"/health", "/metrics"});
registrationBean.setFilter(new CompleteHSTSFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
return registrationBean;
}
}
验证HSTS配置
# 使用curl测试HSTS头 curl -I -k https://yourdomain.com # 期望输出 # Strict-Transport-Security: max-age=31536000; includeSubDomains
注意事项
- 先确保HTTPS正常工作:启用HSTS前,确保所有资源都通过HTTPS提供服务
- 合理设置max-age:开发环境短时间,生产环境至少1年
- 预加载(preload):使用前需提交到浏览器预加载列表
- 排除健康检查路径:避免影响监控系统
通过以上实现,您的Java应用就可以正确配置HSTS,提高Web安全性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播