Spring/Spring MVC/iBATIS 应用 HTTP 到 HTTPS 迁移技术方案
概述
本方案详细介绍了将基于 Spring、Spring MVC 和 iBATIS 的传统 Java Web 应用从 HTTP 迁移到 HTTPS 的完整流程。这种传统架构的迁移需要考虑更多手动配置和兼容性问题。
一、环境评估与准备工作
1.1 当前环境分析
首先需要确认当前应用的技术栈和部署环境:
# 检查当前应用的技术栈
- Spring Framework 版本: 3.x/4.x
- Spring MVC
- iBATIS 2.x (或早期 MyBatis)
- Servlet 容器: Tomcat 7.x/8.x
- Java 版本: 1.7/1.8
- 部署方式: WAR 包部署
1.2 迁移前检查清单
- 确认应用中没有硬编码的 HTTP URL
- 检查所有外部资源引用(CSS、JS、图片等)
- 确认第三方集成支持 HTTPS
- 备份当前应用和配置文件
- 准备回滚方案
二、证书获取与配置
2.1 证书选择与获取
对于传统应用,推荐使用 Java Keystore (JKS) 格式的证书:
# 使用 keytool 生成自签名证书(仅用于测试)
keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 \-keystore tomcat.keystore -validity 3650 \-dname "CN=yourdomain.com, OU=IT, O=YourCompany, L=City, ST=State, C=CN" \-storepass changeit -keypass changeit# 生产环境应使用正式证书,可从 CA 购买或使用 Let's Encrypt
2.2 证书转换(如需要)
如果已有 PEM 格式证书,转换为 JKS 格式:
# 将 PEM 转换为 PKCS12
openssl pkcs12 -export -in certificate.pem -inkey private.key \-out certificate.p12 -name tomcat -CAfile ca_bundle.pem -caname root# 将 PKCS12 转换为 JKS
keytool -importkeystore -deststorepass changeit -destkeypass changeit \-destkeystore tomcat.keystore -srckeystore certificate.p12 \-srcstoretype PKCS12 -srcstorepass changeit -alias tomcat
三、Tomcat 服务器配置
3.1 server.xml 配置
编辑 Tomcat 的 conf/server.xml
文件,添加或修改 Connector 配置:
<!-- 在server.xml中添加HTTPS连接器 -->
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"port="8443" maxThreads="200"scheme="https" secure="true" SSLEnabled="true"keystoreFile="${catalina.home}/conf/tomcat.keystore"keystorePass="changeit"clientAuth="false" sslProtocol="TLS"keyAlias="tomcat"ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA"
/><!-- 配置HTTP连接器重定向到HTTPS -->
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
3.2 web.xml 配置
在应用的 WEB-INF/web.xml
中添加安全约束,强制使用 HTTPS:
<security-constraint><web-resource-collection><web-resource-name>Secure Content</web-resource-name><url-pattern>/*</url-pattern></web-resource-collection><user-data-constraint><transport-guarantee>CONFIDENTIAL</transport-guarantee></user-data-constraint>
</security-constraint>
四、应用层配置调整
4.1 Spring 配置更新
在 Spring 配置文件中确保应用正确处理 HTTPS:
<!-- 在applicationContext.xml或相关配置文件中 -->
<bean id="forceHttpsFilter" class="com.yourcompany.filters.ForceHttpsFilter"/><bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"><property name="webBindingInitializer"><bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"><property name="validator" ref="validator"/></bean></property><!-- 确保URL生成使用HTTPS --><property name="messageConverters"><list><ref bean="mappingJacksonHttpMessageConverter"/></list></property>
</bean>
4.2 自定义 HTTPS 过滤器
创建自定义过滤器处理 HTTPS 重定向和协议头:
package com.yourcompany.filters;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class ForceHttpsFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化代码}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;// 检查是否已经是HTTPSif (!httpRequest.isSecure()) {String requestURL = httpRequest.getRequestURL().toString();String redirectURL = requestURL.replaceFirst("http", "https").replaceFirst(":8080", ":8443");httpResponse.sendRedirect(redirectURL);return;}// 设置响应头增强安全性httpResponse.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");httpResponse.setHeader("X-Content-Type-Options", "nosniff");httpResponse.setHeader("X-Frame-Options", "DENY");httpResponse.setHeader("X-XSS-Protection", "1; mode=block");chain.doFilter(request, response);}@Overridepublic void destroy() {// 清理代码}
}
4.3 更新所有硬编码的 HTTP URL
检查并更新代码中所有硬编码的 HTTP URL:
// 在属性文件或配置类中定义基础URL
public class AppConfig {public static final String BASE_URL = "https://yourdomain.com:8443";// 或者从配置文件读取@Value("${app.baseUrl}")private String baseUrl;
}// 使用配置的URL而不是硬编码
String apiUrl = AppConfig.BASE_URL + "/api/endpoint";
五、iBATIS/SQL Map 配置检查
确保 iBATIS 配置中没有硬编码的 HTTP URL:
<!-- 检查iBATIS配置文件中的任何URL引用 -->
<select id="getExternalData" parameterClass="java.lang.String" resultClass="java.util.HashMap"><!-- 确保没有硬编码的HTTP URL -->SELECT * FROM external_services WHERE protocol = 'https'
</select>
六、前端资源调整
6.1 更新所有资源引用
确保所有前端资源使用协议相对URL或HTTPS URL:
<%-- 在JSP页面中 --%>
<!-- 使用协议相对URL -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<!-- 或直接使用HTTPS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
6.2 处理混合内容问题
添加内容安全策略头防止混合内容:
// 在过滤器或拦截器中添加
response.setHeader("Content-Security-Policy", "default-src 'self' https:; " +"img-src 'self' https: data:; " +"script-src 'self' https: 'unsafe-inline' 'unsafe-eval'; " +"style-src 'self' https: 'unsafe-inline'");
七、部署与测试
7.1 部署流程
- 备份当前应用和配置
- 将证书文件复制到 Tomcat 的 conf 目录
- 更新 server.xml 和 web.xml 配置
- 重新打包应用(如果需要更新代码)
- 部署应用到测试环境
- 重启 Tomcat 服务器
7.2 测试验证
创建全面的测试计划:
# 使用OpenSSL测试SSL连接
openssl s_client -connect yourdomain.com:8443 -servername yourdomain.com# 使用curl测试重定向
curl -I http://yourdomain.com:8080
# 应该返回301/302重定向到HTTPS# 测试HTTPS连接
curl -k https://yourdomain.com:8443
测试用例应包括:
- HTTP 到 HTTPS 的重定向
- 所有主要功能在 HTTPS 下的可用性
- 静态资源加载(无混合内容警告)
- 表单提交和数据传输
- 会话保持和Cookie安全
- 第三方集成功能
八、监控与维护
8.1 日志配置
增强日志记录以监控SSL相关问题:
<!-- 在log4j.properties或logback.xml中 -->
<logger name="org.apache.coyote.http11" level="DEBUG"/>
<logger name="org.apache.tomcat.util.net" level="INFO"/>
8.2 证书维护
设置证书过期提醒和续订流程:
# 检查证书过期日期
keytool -list -v -keystore tomcat.keystore | grep -i valid# 设置定期检查任务(crontab)
0 0 1 * * /path/to/check_cert_expiry.sh
九、回滚方案
如果迁移遇到问题,按以下步骤回滚:
- 恢复原来的 server.xml 配置
- 移除 web.xml 中的安全约束
- 恢复应用代码中的URL引用
- 重启 Tomcat 服务器
- 验证应用恢复正常HTTP访问
十、常见问题与解决方案
10.1 会话丢失问题
HTTPS 和 HTTP 的会话可能不共享,需要确保会话连续性:
// 在应用初始化时设置Cookie为安全
Cookie cookie = new Cookie("JSESSIONID", sessionId);
cookie.setSecure(true);
cookie.setHttpOnly(true);
response.addCookie(cookie);
10.2 性能考虑
SSL/TLS 加密会增加服务器负载,考虑:
- 启用 TLS 会话恢复
- 使用更高效的加密算法
- 考虑硬件SSL加速(如需要)
10.3 兼容性问题
确保所有客户端和浏览器支持使用的加密算法:
<!-- 在server.xml中配置兼容的加密套件 -->
<Connectorciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA"
/>
总结
将传统 Spring/Spring MVC/iBATIS 应用从 HTTP 迁移到 HTTPS 需要以下关键步骤:
- 证书准备 - 获取并配置合适的 SSL 证书
- 服务器配置 - 修改 Tomcat 的 server.xml 和应用的 web.xml
- 应用层调整 - 更新代码中的 URL 引用,添加安全过滤器
- 前端资源处理 - 确保所有资源使用 HTTPS 或协议相对 URL
- 全面测试 - 验证功能正常且无混合内容问题
- 监控维护 - 设置证书过期监控和性能监控
与传统 Spring Boot 应用相比,这种架构的迁移需要更多手动配置,但通过系统化的方法可以确保平稳过渡。务必在生产环境部署前进行充分的测试,并准备好回滚方案。