Pau*_*lan 3 java ssl apache-httpclient-4.x tls1.2 mtls
背景
使用以下http客户端
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
我的假设 在管理连接池中的连接时,选择连接时,应在选择连接池中的相同连接之前考虑客户端证书。我不希望使用 clientB TLS 证书连接 clientA,反之亦然。
问题 这个假设正确吗?
场景1)
我将每条路由的最大连接数设置为 2。我调用客户端 A 的 MTLS 安全服务器。(池中的一个连接) 我调用客户端 A 的 MTLS 安全服务器。(池中两个连接)这不应该重用第一个连接吗?
场景2)
我将每条路由的最大连接数设置为 2。我为客户端 A 调用 MTLS 安全服务器。(池中的一个连接)我为客户端 B 调用 MTLS 安全服务器。(池中两个连接)
然而,第二次调用似乎没有执行完整的握手,而是使用了 clientA 证书。
我希望第二次调用需要完整的握手,并且连接无论如何都不相关。
这是预期的行为吗?我在这里遗漏了一些明显的东西吗?
更新了更简单的测试用例
我们现在使用 http 上下文,因此我附上了更新的日志。我也简化了测试用例,现在它每次都连接到同一服务器两次,应该使用不同的客户端证书。
该应用程序使用 Spring Boot,并具有单个 RestTemplate 和单个 httpClient。
它使用 PrivateKeyStrategy 来决定与服务器通信时使用什么私钥/证书。
第一个连接使用密钥别名“e2e_transport_key_id_franek”(您将在日志中看到这一点)
第二个连接应使用别名“e2e_transport_key_id_pdw”(日志中从未见过)
我们建立的第二个连接应该使用别名为“e2e_transport_key_id_pdw”的密钥/证书,但是会话已恢复,请参见第 448 行尝试恢复会话。这意味着我们无法使用 PrivateKeyStrategy 来选择要使用的客户端证书。
如何强制客户端连接不重复使用我们打算使用不同客户端证书的连接的会话?
这个假设是真的吗?
你的假设是正确的。连接池用于请求和释放连接的方法都采用名称为state的附加参数。此状态参数通常采用用户令牌,或者null如果没有进行身份验证。
仅当使用与将连接释放回连接池相同的用户令牌请求连接时,才能重新使用连接。
此机制也适用于 SSL 客户端证书。成功 SSL 握手后,SSL 连接将与代表用户令牌的X500Principal一起释放。该令牌也存储在HttpContext用于请求的对象中。要在后续 HTTP 请求中重新使用已释放的连接,您还必须重新使用HttpContext第一个 HTTP 请求的连接。
场景1
clientA.execute(new HttpGet("..."));
clientA.execute(new HttpGet("..."));
Run Code Online (Sandbox Code Playgroud)
第一个请求触发完整的 SSL 握手。使用用户令牌释放连接。HttpContext第二个请求使用不包含任何用户令牌的新请求。因此,池中的连接无法重复使用,并且会通过完全握手创建新连接。
场景2
HttpContext context = new HttpClientContext();
clientA.execute(new HttpGet("..."), context);
clientB.execute(new HttpGet("..."), context);
Run Code Online (Sandbox Code Playgroud)
如前所述,用户令牌存储在HttpContext. 因此,如果您重新使用HttpContext第一个请求中的连接,即使您使用具有不同连接工厂/客户端证书的不同客户端,第二个请求也可以重新使用已经存在的连接。如果该连接正在使用,则会使用 clientB 的连接工厂创建一个新连接。
要分离clientA和clientB并确保仅每个客户端重复使用连接,您必须为每个HttpContext客户端使用一个连接并为每个请求重复使用上下文:
HttpContext contextA = new HttpClientContext();
clientA.execute(new HttpGet("..."), contextA);
clientA.execute(new HttpGet("..."), contextA);
HttpContext contextB = new HttpClientContext();
clientB.execute(new HttpGet("..."), contextB);
Run Code Online (Sandbox Code Playgroud)
请注意,如果出现会话超时或请求重新协商,即使连接被重用,也可能需要完全握手。
| 归档时间: |
|
| 查看次数: |
2627 次 |
| 最近记录: |