HTTP连接在内部使用java.net.Socket类的对象来处理数据在线路上的传输。 然而,他们依靠 ConnectionSocketFactory接口来创建,初始化和连接Socket。HttpClient的使用者能够在运行时,提供应用程序特定的Socket初始化代码。PlainConnectionSocketFactory类是创建和初始化普通(未加密)套接字的默认工厂类。
创建一个套接字和连接到主机的过程是解耦的,以便连接操作被阻塞的时候套接字能够被关闭
HttpClientContext clientContext = HttpClientContext.create(); PlainConnectionSocketFactory sf = PlainConnectionSocketFactory.getSocketFactory(); Socket socket = sf.createSocket(clientContext); int timeout = 1000; //ms HttpHost target = new HttpHost("localhost"); InetSocketAddress remoteAddress = new InetSocketAddress( InetAddress.getByAddress(new byte[] {127,0,0,1}), 80); sf.connectSocket(timeout, socket, target, remoteAddress, null, clientContext);
LayeredConnectionSocketFactory接口是 ConnectionSocketFactory接口的扩展。阶层式套接字工厂能够在现有普通套接字上创建层次化的套接字。层次化套接字主要用于通过代理创建安全套接字。
HttpClient附带了实现SSL / TLS分层的SSLSocketFactory类。请注意 HttpClient 不使用任何自定义的加密功能,它完全依赖于 Java 加密 (JCE) 和安全套接字 (JSEE) 扩展标准。
自定义连接套接字工厂可以与特定的协议方案相关联,如HTTP或HTTPS,然后用来创建自定义连接管理器。
ConnectionSocketFactory plainsf = <...> LayeredConnectionSocketFactory sslsf = <...> Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", plainsf) .register("https", sslsf) .build(); HttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(r); HttpClients.custom() .setConnectionManager(cm) .build();
HttpClient 利用 SSLConnectionSocketFactory类创建 SSL 连接。SSLConnectionSocketFactory类允许高度自定义,可以把javax.net.ssl.SSLContext接口的实例作为参数传入,并使用它来创建自定义配置的SSL连接。
KeyStore myTrustStore = <...> SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial(myTrustStore) .build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
对SSLConnectionSocketFactory类自定义意味着对SSL / TLS协议的概念有一定程度的了解,其详细说明不在本文档范围内。请点击
Java™ Secure Socket Extension (JSSE) Reference Guide 来获取javax.net.ssl.SSLContext接口和相关工具的详细说明。
除了在SSL / TLS协议级别上进行信任验证和客户端身份验证之外,一旦建立了连接,HttpClient可以选择性地验证目标主机名是否与存储在服务器的X.509证书中的名称匹配。该验证可以提供对服务器信任材料的真实性的额外保证。javax.net.ssl.HostnameVerifier接口代表主机名验证策略。 HttpClient附带了javax.net.ssl.HostnameVerifier接口的两个实现类。重要:主机名验证和SSL信任验证这两者不应混淆。
-
DefaultHostnameVerifier: HttpClient使用的默认实现类,它应兼容RFC 2818。主机名必须匹配证书指定的任何别名,或在证书持有者没有为别名给出最明确的证书通用名(CN)的情况下。 在证书通用名(CN),以及任何subject-alts中都可以出现通配符。
-
NoopHostnameVerifier类: 作为主机名验证工具,实质上关闭了主机名验证,它接受任何有效的SSL会话并匹配到目标主机。
HttpClient默认使用DefaultHostnameVerifier类来实现。 如果需要,可以指定其他的主机名验证器来实现。
SSLContext sslContext = SSLContexts.createSystemDefault(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslContext, NoopHostnameVerifier.INSTANCE);
自版本4.4后HttpClient使用由Mozilla基金维护的公共后缀名列表,以确保SSL证书中的通配符不会被滥用于申请拥有公共顶级域名的多个域。 HttpClient 附带了在释放时回收的列表的副本。 https://publicsuffix.org/list/这个URL能够获取最近的版本号列表,强烈建议制作这个列表的本地副本,并每天从其原始位置下载不超过一次。
PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load( PublicSuffixMatcher.class.getResource("my-copy-effective_tld_names.dat")); DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
可以使用“null”这个参数来禁用对公共后缀名列表的验证。
DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(null);
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/114013.html