如何在Jetty Embedded 9.x中禁用主机名及证书验证(指定方法无效)
兄弟,我太懂你这种配置半天没生效的郁闷了!Jetty 9.3.x的SSL配置确实有几个容易踩的坑,你用的setTrustAll(true)和setEndpointIdentificationAlgorithm(null)其实只解决了一部分问题,主机名验证还有单独的控制逻辑,下面给你一步步解决:
1. 先确认你用对了SslContextFactory
如果你是让Jetty当客户端(比如用Jetty的HttpClient或WebSocketClient连接外部服务),一定要用SslContextFactory.Client,别用SslContextFactory.Server——后者是给服务器端用的,配置逻辑完全不一样,用错了肯定白搭。
2. 显式干掉主机名验证器
Jetty 9.3.x里,哪怕你把端点识别算法设为null,它还有个HostnameVerifier在默默做校验。直接把这个验证器改成“啥都通过”就行:
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); sslContextFactory.setTrustAll(true); // 关掉Java自带的端点识别 sslContextFactory.setEndpointIdentificationAlgorithm(null); // 强制所有主机名都通过验证 sslContextFactory.setHostnameVerifier((hostname, session) -> true);
用lambda写个返回true的验证器,简单粗暴但有效,也可以直接把HostnameVerifier设为null,效果一样。
3. 如果是服务器端要关客户端证书验证
要是你的需求是Jetty服务器自己接收SSL连接时,不用验证客户端证书的主机名,那得改服务器端的SslContextFactory.Server配置:
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); // 关掉客户端证书的有效性和主机名验证 sslContextFactory.setValidateCerts(false); sslContextFactory.setValidatePeerCerts(false); // 要是完全不需要客户端证书,直接把客户端认证关了更彻底 sslContextFactory.setNeedClientAuth(false); sslContextFactory.setWantClientAuth(false);
这里的setValidateCerts和setValidatePeerCerts就是控制服务器端对客户端证书的校验,设为false就全关了。
4. 检查配置有没有被覆盖
最后再确认下,你自定义的SslContextFactory是不是真的关联到了Jetty的连接器上,别让默认配置给覆盖了。比如配置HTTPS连接器的时候要这样写:
Server server = new Server(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); // 把刚才的配置都加上 sslContextFactory.setTrustAll(true); sslContextFactory.setEndpointIdentificationAlgorithm(null); sslContextFactory.setHostnameVerifier((hostname, session) -> true); // 把SSL工厂关联到连接器 SslConnectionFactory sslConnFactory = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()); HttpConnectionFactory httpConnFactory = new HttpConnectionFactory(new HttpConfiguration()); ServerConnector sslConnector = new ServerConnector(server, sslConnFactory, httpConnFactory); sslConnector.setPort(8443); server.addConnector(sslConnector);
确保所有SSL相关的配置都走你自己的这个工厂,别用Jetty默认的。
为啥你之前的配置没生效?
说白了,setTrustAll(true)只是让SSL信任所有证书,但主机名验证是Jetty单独用HostnameVerifier控制的,setEndpointIdentificationAlgorithm(null)是关掉Java自带的那层校验,但Jetty自己的验证器还在跑,所以必须显式把它改成“全通过”才行。
内容的提问来源于stack exchange,提问作者trili

