旧版Embedded Jetty SSL嵌入代码无法正常运行求助
嵌入式Jetty SSL协议错误修复方案
问题背景
一段长期运行的Embedded Jetty SSL嵌入代码近期访问时触发浏览器协议错误,同类示例代码也出现相同问题,已排除证书问题(证书在其他应用中可正常使用)。
现有代码
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.server.handler.AbstractHandler; public class EmbeddedJettyHTTPS { public static void main(String[] args) throws Exception { Server server = new Server(); server.setHandler ( new HelloServlet()); ServerConnector connector = new ServerConnector(server); connector.setPort(9999); HttpConfiguration https = new HttpConfiguration(); https.addCustomizer(new SecureRequestCustomizer()); SslContextFactory sslContextFactory = new SslContextFactory("/myDirecotry/mykeystore"); sslContextFactory.setKeyStorePassword("myPassword"); ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"), new HttpConnectionFactory(https)); sslConnector.setPort(8443); sslConnector.setIdleTimeout(50000); server.setConnectors(new Connector[]{ sslConnector }); server.start(); server.join(); } public static class HelloServlet extends AbstractHandler { @Override public void handle( String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException { // Declare response encoding and types response.setContentType("text/html; charset=utf-8"); // Declare response status code response.setStatus(HttpServletResponse.SC_OK); // Write back response response.getWriter().println("<h1>Hello World</h1>"); // Inform jetty that this request has now been handled baseRequest.setHandled(true); } } }
核心问题与修复操作
1. SslContextFactory API版本变更
Jetty 10及后续版本重构了SSL上下文工厂的设计:
- 原
SslContextFactory默认切换为客户端模式,服务器端必须使用SslContextFactory.Server子类 - 构造参数不再直接接收密钥库路径,需通过
setKeyStorePath方法设置
修复代码:
// 替换原SslContextFactory初始化逻辑 SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath("/myDirecotry/mykeystore"); sslContextFactory.setKeyStorePassword("myPassword");
2. 协议标识规范问题
SslConnectionFactory的第二个参数需使用标准大写的"HTTP/1.1",部分新版本Jetty对小写标识的兼容性下降,会导致协议协商失败。
修复代码:
ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "HTTP/1.1"), new HttpConnectionFactory(https));
3. TLS协议版本适配
现代浏览器默认禁用TLSv1.0、TLSv1.1,若Jetty未启用TLSv1.2+会触发协议不兼容。
补充配置:
// 启用现代TLS版本 sslContextFactory.setIncludeProtocols("TLSv1.2", "TLSv1.3"); // 配置兼容现代浏览器的加密套件 sslContextFactory.setIncludeCipherSuites( "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256" );
4. 清理冗余代码
原代码中初始化了端口9999的HTTP连接器但未加入服务器配置,属于冗余代码,建议删除:
// 删除以下无效代码块 ServerConnector connector = new ServerConnector(server); connector.setPort(9999);
内容的提问来源于stack exchange,提问作者Unhandled Exception
相关产品推荐
相关产品推荐

