如何向 HTTP 客户端传递客户端证书?

2023-11-22

我想在服务 A 和 B 之间使用相互 SSL 身份验证。我目前正在使用 Java 实现从服务 A 传递客户端证书。我正在使用 Apache DefaultHttpClient 来执行我的请求。我能够从内部凭证管理器检索服务 A 的客户端证书,并将其保存为字节数组。

DefaultHttpClient client = new DefaultHttpClient();
byte [] certificate = localCertManager.retrieveCert();

我在这方面的经验很少,非常感谢您的帮助!

我想也许它应该以某种方式通过 HTTP 客户端中的参数或者标头中的参数传递。

如何向 HTTP 客户端传递客户端证书?


客户端证书是在 TLS 握手期间发送建立连接时无法通过该连接内的 HTTP 发送。

通信是这样分层的:

  • HTTP(应用层协议)内
  • TLS(表示层协议)
  • TCP(传输层协议)内
  • IP(网络层协议)

您需要在 TLS 握手期间发送客户端证书,然后才能影响任何 HTTP(方法、标头、URL、请求正文)。服务器将不接受稍后发送的客户端证书。

我建议从默认HttpClient(已弃用)至可关闭的HttpClient与 try-with-resources 一起使用会更干净。

Apache HttpClient 4.5使双向 TLS 相当方便。这个答案已经过测试阿帕奇 HttpClient 4.5.3.

基本的出发点是使用加载KeyMaterial将您的客户端证书及其密钥(客户端密钥对)加载到SSL上下文:

SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(
                MutualHttpsMain.class.getResource(TEST_CLIENT_KEYSTORE_RESOURCE),
                storePassword, keyPassword,
                (aliases, socket) -> aliases.keySet().iterator().next()
        ).build();

最后使用该套接字工厂构建一个 HTTP 客户端:

CloseableHttpClient httpclient = HttpClients
        .custom().setSSLContext(sslContext).build();

使用该客户端,您的所有请求都可以通过隐含的相互 TLS 身份验证来执行:

CloseableHttpResponse closeableHttpResponse = httpclient.execute(
        new HttpGet(URI.create("https://mutual-tls.example.com/")));

以下是使用 Apache HttpClient 的双向 TLS 的完整可运行示例:

import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;

import javax.net.ssl.SSLContext;
import java.io.Console;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.security.GeneralSecurityException;

public class MutualHttpsMain {
    private static final String TEST_URL = "https://mutual-tls.example.com/";
    private static final String TEST_CLIENT_KEYSTORE_RESOURCE = "/mutual-tls-keystore.p12";

    public static void main(String[] args) throws GeneralSecurityException, IOException {
        Console console = System.console();
        char[] storePassword = console.readPassword("Key+Keystore password: ");
        char[] keyPassword = storePassword;
        SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(
                MutualHttpsMain.class.getResource(TEST_CLIENT_KEYSTORE_RESOURCE),
                storePassword, keyPassword,
                (aliases, socket) -> aliases.keySet().iterator().next()
        ).build();
        try (CloseableHttpClient httpclient = HttpClients
                .custom().setSSLContext(sslContext).build();
             CloseableHttpResponse closeableHttpResponse = httpclient.execute(
                    new HttpGet(URI.create(TEST_URL)))) {
            console.writer().println(closeableHttpResponse.getStatusLine());
            HttpEntity entity = closeableHttpResponse.getEntity();
            try (InputStream content = entity.getContent();
                 ReadableByteChannel src = Channels.newChannel(content);
                 WritableByteChannel dest = Channels.newChannel(System.out)) {
                ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
                while (src.read(buffer) != -1) {
                    buffer.flip();
                    dest.write(buffer);
                    buffer.compact();
                }
                buffer.flip();
                while (buffer.hasRemaining())
                    dest.write(buffer);
            }
        }
    }
}

一般来说,使用 Gradle 或 Maven 来运行这样的东西会更好,但为了尽可能减少 Yak shave,我提供了用于构建和运行它的基线 JDK 指令。

从以下页面下载 JAR:

  • 阿帕奇 HttpClient 4.5.3
  • Apache 通用编解码器 1.10
  • Apache Commons 日志记录 1.2
  • 阿帕奇 HttpCore 4.4.8

将上面的完整示例另存为MutualHttpsMain.java.

将您的 PKCS#12 复制到相互 tls-keystore.p12在同一目录中。

按如下方式编译(在 macOS/Linux/*nix-likes 上):

javac MutualHttpsMain.java -cp httpclient-4.5.3.jar:httpcore-4.4.8.jar

或者在 Windows 上:

javac MutualHttpsMain.java -cp httpclient-4.5.3.jar;httpcore-4.4.8.jar

运行如下(在 macOS/Linux/*nix-likes 上):

java -cp httpclient-4.5.3.jar:commons-codec-1.10.jar:commons-logging-1.2.jar:httpcore-4.4.8.jar:. MutualHttpsMain

运行如下(在 Windows 上):

java -cp httpclient-4.5.3.jar;commons-codec-1.10.jar;commons-logging-1.2.jar;httpcore-4.4.8.jar;. MutualHttpsMain
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何向 HTTP 客户端传递客户端证书? 的相关文章

  • 如何在 Java 中使用 HTML 解析器和 Apache Tika 来提取所有 HTML 标签?

    我下载了 tika core 和 tika parser 库 但找不到将 HTML 文档解析为字符串的示例代码 我必须删除网页源的所有 html 标签 我能做些什么 如何使用 Apache Tika 进行编码 您想要 html 文件的纯文本
  • 在apache中有条件地设置缓存头

    我想根据访问文件的路径有条件地设置缓存标头 基本上 访问http www example com cache cache key 应该为具有遥远未来缓存标头的文件提供服务 我使用重写规则来设置环境变量 然后尝试根据该变量设置缓存控制标头 然
  • 如何用 C++ 编写 Apache 模块?

    我想用 C 编写一个 Apache 模块 我尝试了一个非常准系统的模块来启动 include httpd h include http core h include http protocol h include http request
  • 强制 Apache HTTPD 以 32 位运行

    我通过从二进制文件 以及 ppc 部分 中剥离 32 位架构 以 64 位模式运行 Apache HTTPD 我这样做是为了使其与 python 和 mysql 更加兼容 然而 我有另一台机器需要它以 32 位模式运行 它仍然保留所有四种原
  • apache_request_headers() 与 $_SERVER

    据我所知 apache request headers 提供与以下相同的信息 SERVER 但按键略有不同 为什么有人应该使用apache request headers 而不仅仅是从那里获取这些信息 SERVER 我在 Centos 上使
  • URL 中的 %2F 中断并且未引用所需的 .php 文件 [重复]

    这个问题在这里已经有答案了 我需要将 作为变量作为 URL 的一部分传递 我的结构如下所示 www domain com listings page 1 city Burnaby South type Townhome bedroom 2
  • 使用 HTTPS 时我需要/想要 gzip 压缩吗?

    使用 HTTPS 是否已经包含 透明 内容压缩 或者我是否仍然应该担心与浏览器协商是否压缩我的 Servlet 输出 如果 HTTPS 已经有压缩 是无条件的还是需要配置 协商 启用 默认情况下 TLS 不启用压缩 但它 压缩 是在 TLS
  • 将混合内容重定向到 HTTPS 的正确 htaccess 规则是什么

    当通过 HTTPS 访问网站时 是否有一种方法可以使用 htaccess 重定向条件和重定向来捕获通过 HTTP 调用的内容 如果通过 HTTPS 访问网站 http 内容将被重定向到 https 等效 url 本质上 当我的网站通过 HT
  • Mod_Rewrite 将子域和目录设置为 GET 变量

    我编写了一个想要多语言的网站 应该可以通过子域访问不同的语言 例如 en example com de example com 等 此外 我已经重写了将 目录 设置为 GET 变量 将 example com name 更改为 exampl
  • .htaccess 如果 URL 错误,请执行某些操作

    我正在做我的个人CMS http en wikipedia org wiki Content management system 我想在其中使用很酷 友好 的 URL 这是我的 htaccess 文件代码 RewriteEngine on
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 为什么 Tomcat 缺少内置的速率限制过滤器?

    从几个来源 1 https serverfault com questions 177742 2 http tomcat 10 x6 nabble com tomcat bandwidth limiter transfer rate lim
  • 使用 Internet Explorer 和 SSL 时如何启用自动完成功能?

    当以下两个条件都成立时 1 The page was delivered over HTTPS 2 The page was delivered with headers or a META tag that prevents cachin
  • 在 Tomcat 8 上配置 SSL 并连接超时

    我设置了一个密钥库并从 openssl com 获得了 SSL 证书 我遵循的具体步骤在这里 https drive google com file d 0B6PUGo7cBLcDTzdkc0pzT2pTMk0 view usp shari
  • CNAME 速度慢吗?

    我将 CNAME 与 S3 CloudFront 一起使用来提供一些静态文件 例如 js css 图像等 我这样做是为了使存储桶的 URL 更漂亮 因为我认为最好将所有内容都定位到我的网站 以防万一将来我想移动这些文件 更改应该是透明的 今
  • mod_rewrite 将 example.com/page.php?v1=abc&v2=def 重写为 example.com/abc/def

    Using Apache s htaccess文件 我正在尝试rewrite网址http example com page php v1 abc v2 def to http example com abc def 到目前为止我有 Opti
  • 无法将 TXT 记录设置为 Freenom 提供商中的域

    我想为分配给 Azure 中 WordPress 的域启用 SSL 我的域名是在 Freenom 中创建的 要完成该过程 我需要从 Azure 手动验证域 Azure 域验证 https i stack imgur com 4park jp
  • 通过 Java 连接 Apache Drill

    在 Apache Drill 的 Wiki 中 我只能看到通过 SqlLine 客户端运行的查询 除了 REST API 之外 是否有任何编程方式可以在 Drill 中运行查询 有任何示例或指示吗 或者它与使用 JDBC 驱动程序运行 SQ
  • 使用 Android WebViewClient 启用特定 SSL 协议

    我的应用程序使用WebViewClient与服务器建立 SSL 连接 服务器配置为仅接受 TLSv1 1 及以上协议 使用 Android 时 如何检查哪些 SSL 协议是 a 支持的和 b 默认启用的WebViewClient在设备上 如
  • 使用 mod_proxy 进行反向代理,保留原始请求 URL

    我已经使用 mod proxy Apache2 配置了一个反向代理 监听 127 0 0 1 80 将所有请求代理到 127 0 0 1 8080 所以我配置了 mod proxy 如下所示 ProxyPreserveHost On Pro

随机推荐

  • 从数据库填充 DropDownList 的正确方法是什么?

    我正在从 SQL Server 数据库填充 DropDownList 如下所示 它工作得很好 但我不确定这是一个好方法 有人可以阐明这种方法并进行一些改进吗 private void LoadSubjects ddlSubjects Ite
  • Android Gradle 代码覆盖率

    我有一个带有测试用例的简单 Android 项目 ProjNameProject build gradle ProjName build gradle 我看到默认情况下android的新构建系统默认提供基本的测试结果 万岁 现在我还想查看代
  • 错误 - 多次出现具有不同值的“contentType”是非法的

    我在 Eclipse 中有一个动态 Web 项目 在 Glassfish4 上运行 在项目中 有一个如下所示的index jsp文件 当我在服务器上运行这个jsp时 出现错误 org apache jasper JasperExceptio
  • 在Windows上构建hadoop 2.2

    我正在尝试在windows上安装hadoop 到目前为止还很麻烦 这是我不断收到的错误 ERROR Failed to execute goal org codehaus mojo exec maven plugin 1 2 exec co
  • 我可以使用 Laravel 5 中间件来允许包覆盖应用程序路由吗?

    我希望能够使用包中的路由覆盖 app Http routes php 中定义的路由 例如 在 app Http routes php 中我可能有这个 Route get search type as gt search uses gt Se
  • 如何在没有科学记数法的 R 数据框中显示数字列('e+07')

    我有一个 R 数据框 其中一列包含一串数字 但我想将它们视为一个因素 主要是为了阻止 R 使用 e 04 等缩短数字 我发现解决此问题的一种方法是编辑从中获取数据的 csv 文件 并添加一个在所需列中包含单词的虚拟条目 然后重新导入它 如何
  • 如何将 facebook、twitter 和 google plus 集成到 Android 应用程序中

    我喜欢将 Facebook Twitter 和 Google plus 集成到我的应用程序中 以便使用该应用程序的用户可以更新他们的状态 因此我想知道如何做到这一点 Thanks 我强烈建议不要使用这些 SDK 因为它们包含很多错误 而且据
  • 如何获取默认 NIC 连接名称

    重要编辑 再次回到这个话题 正如您所说不应该有默认的网卡 我试图了解是否有一种方法可以检测实际连接的所有网卡 有了我的物理接口的 MAC 地址 是否有一种编程方式来获取接口名称 接口状态 等 比如我的XP机器 设备 Realtek RTL8
  • 自动递增 bigint 列?

    我想要插入表中的每一行数据都有一个 bigint ID 列 我想要 Sql 服务器生成数字 我尝试创建一个具有 bigint 列 ID 的表 我希望这是自动增量 第一个值为 1 我尝试使用 ID bigint AUTO INCREMENT
  • 将数据从 Props 传递到 vue.js 中的数据

    我有以下 vue 组件
  • 在 Rust 中使用枚举实现动态多态性

    当人们已经知道某些需要动态多态性的代码中涉及的所有有限数量的类型时 使用enum与使用相比 可以更好地提高性能Box因为后者使用动态内存分配 并且您需要使用也具有虚拟函数调用的特征对象 也就是说 与 C 中使用的等效代码相比std vari
  • 如何配置 IIS,以便在连接到 SQL Server 时使用用户的域凭据?

    我们最近发布了最新版本的 Intranet 应用程序 该应用程序现在使用 Windows 身份验证作为标准 并且需要能够使用最终用户的域凭据连接到已配置的 SQL 服务器 最近我们发现 在一些客户部署中 尽管 IIS 可以看到用户的域凭据
  • 是否可以在 .NET 4 中动态创建路由?

    在我们的应用程序中 我们使用新的 NET 4 路由系统将某些请求路由到站点的其他部分 我们只允许在深夜发布我们的网站代码 这意味着我们必须加班到很晚才能发布任何代码更改 我们经常需要创建自定义路由来支持旧内容的旧链接并将其路由到新内容 这些
  • Adobe Media Encoder 是否可以使用 ExtendScript 编写脚本?

    Adobe Media Encoder AME 是否可以编写脚本 我听人们提到它是 官方可编写脚本的 但我找不到任何对其可编写脚本的对象集的引用 有人有编写 AME 脚本的经验吗 Adobe 媒体编码器 正式 不可编写脚本 但我们可以使用扩
  • Windows 窗体:如何更改禁用标签的字体颜色

    我正在尝试为标签控件设置禁用的字体特征 我可以设置所有字体特征 大小 粗体等 但颜色被默认的窗口行为覆盖 这似乎是这两种颜色之一 如果背景颜色是透明的 则前景色与文本框禁用颜色相同 如果背景颜色设置为其他颜色 则前景色为深灰色 下图演示了该
  • SQLAlchemy:将查询结果插入到另一个表中

    所以我得到了一些结果install表 像这样 install metadata tables install results session query install
  • Activiti / Camunda 用变量改变边界计时器

    我有一个关于 Activiti Camunda 中用户任务的计时器边界事件的特殊问题 启动流程时 我使用流程变量设置计时器持续时间 并使用边界定义中的表达式来解析该变量 边界事件是在用户任务上定义的
  • Javascript - .innerHTML 更改自动关闭标签

    我正在尝试使用 Javascript 动态地将元素放入其他元素中 而无需刷新页面 它的 AJAX 部分可以工作并且功能正常 然而 由于某种未知的原因 我的代码自动关闭 这是代码片段 您可以看到它实际上并未关闭 但是在浏览器中运行代码后它被关
  • 使用 iOS 的 ExtAudioFileWrite 将音频样本缓冲区写入 aac 文件

    更新 我已经弄清楚了这一点并发布了我的解决方案作为我自己的问题的答案 如下 我正在尝试使用 AAC 格式的 ExtAudioFileWrite 将简单的音频样本缓冲区写入文件 我已经通过下面的代码实现了这一点 将单声道缓冲区写入 wav 文
  • 如何向 HTTP 客户端传递客户端证书?

    我想在服务 A 和 B 之间使用相互 SSL 身份验证 我目前正在使用 Java 实现从服务 A 传递客户端证书 我正在使用 Apache DefaultHttpClient 来执行我的请求 我能够从内部凭证管理器检索服务 A 的客户端证书