使用有效客户端证书时出现 HttpClient 403 错误

2023-12-30

我正在尝试使用 Java 自动执行网站上的一些任务。我有该网站的有效客户端(当我使用 Firefox 登录时有效),但当我尝试使用 http 客户端登录时,我不断收到 403 错误。请注意,我希望我的信任存储信任任何内容(我知道它不安全,但目前我并不担心这一点)。

这是我的代码:

    KeyStore keystore = getKeyStore();//Implemented somewhere else and working ok
    String password = "changeme";

    SSLContext context = SSLContext.getInstance("SSL");
    KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmfactory.init(keystore, password.toCharArray());
    context.init(kmfactory.getKeyManagers(), new TrustManager[] { new X509TrustManager() {
        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }
        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    } }, new SecureRandom());
    SSLSocketFactory sf = new SSLSocketFactory(context);

    Scheme httpsScheme = new Scheme("https", 443, sf);
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(httpsScheme);
    ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
    HttpClient client = new DefaultHttpClient(cm);

    HttpGet get = new HttpGet("https://theurl.com");
    HttpResponse response = client.execute(get);
    System.out.println(EntityUtils.toString(response.getEntity(), "UTF-8"));

最后一条语句打印出 403 错误。我在这里缺少什么?


我自己想出来了。出现 403 错误是因为 Java SSL 没有选择我的客户端证书。

我调试了 SSL 握手,发现服务器要求提供由权威列表颁发的客户端证书,而我的客户端证书的颁发者不在该列表中。因此 Java SSL 根本无法在我的密钥库中找到合适的证书。看起来 Web 浏览器和 Java 实现 SSL 的方式略有不同,因为我的浏览器实际上会询问我要使用哪个证书,无论服务器证书对客户端证书的颁发者有何要求。

在这种情况下,服务器证书是罪魁祸首。它是自签名的,并且它通知的可接受的发行人列表不完整。这与 Java SSL 实现不能很好地混合。但服务器不是我的,我对此无能为力,除了抱怨巴西政府(他们的服务器)。没有进一步的到期,这是我的解决方法:

首先,我使用了信任任何事物的 TrustManager(就像我在问题中所做的那样):

public class MyTrustManager implements X509TrustManager {
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

然后我实现了一个密钥管理器,它始终使用我想要的 PKCS12 (.pfx) 证书中的密钥:

public class MyKeyManager extends X509ExtendedKeyManager {

KeyStore keystore = null;
String password = null;
public MyKeyManager(KeyStore keystore, String password) {
        this.keystore = keystore;
        this.password = password;
}

@Override
public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) {
    return "";//can't be null
}

@Override
public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) {
    return null;
}

@Override
public X509Certificate[] getCertificateChain(String arg0) {
    try {
        X509Certificate[] result = new X509Certificate[keystore.getCertificateChain(keystore.aliases().nextElement()).length];
        for (int i=0; i < result.length; i++){
            result[i] = (X509Certificate) keystore.getCertificateChain(keystore.aliases().nextElement())[i];
        }
        return result ;
    } catch (Exception e) {
    }
    return null;
}

@Override
public String[] getClientAliases(String arg0, Principal[] arg1) {
    try {
        return new String[] { keystore.aliases().nextElement() };
    } catch (Exception e) {
        return null;
    }
}

@Override
public PrivateKey getPrivateKey(String arg0) {
    try {
        return ((KeyStore.PrivateKeyEntry) keystore.getEntry(keystore.aliases().nextElement(),
                new KeyStore.PasswordProtection(password.toCharArray()))).getPrivateKey();
    } catch (Exception e) {
    }
    return null;
}

@Override
public String[] getServerAliases(String arg0, Principal[] arg1) {
    return null;
}

}

This would如果我的 pfx 也包含其颁发者证书,则可以工作。但事实并非如此(耶!)。因此,当我使用上面的密钥管理器时,我收到了 SSL 握手错误(对等点未经过身份验证)。仅当客户端发送服务器信任的证书链时,服务器才会对客户端进行身份验证。由于我的证书(由巴西机构颁发)不包含其颁发者,因此其证书链仅包含其自身。服务器不喜欢这样并拒绝对客户端进行身份验证。解决方法是手动创建证书链:

...
@Override
    //The order matters, your certificate should be the first one in the chain, its issuer the second, its issuer's issuer the third and so on.
public X509Certificate[] getCertificateChain(String arg0) {
            X509Certificate[] result = new X509Certificate[2];
            //The certificate chain contains only one entry in my case
            result[0] = (X509Certificate) keystore.getCertificateChain(keystore.aliases().nextElement())[0];
            //Implement getMyCertificateIssuer() according to your needs. In my case, I read it from a JKS keystore from my database
            result[1] = getMyCertificateIssuer();
            return result;
}
...

之后,只需充分利用我的自定义密钥和信任管理器即可:

            InputStream keystoreContents = null;//Read it from a file, a byte array or whatever floats your boat
            KeyStore keystore = KeyStore.getInstance("PKCS12");
            keystore.load(keystoreContetns, "changeme".toCharArray());
            SSLContext context = SSLContext.getInstance("TLSv1");
            context.init(new KeyManager[] { new MyKeyManager(keystore, "changeme") },
                            new TrustManager[] { new MyTrustManager() }, new SecureRandom());
            SSLSocketFactory sf = new SSLSocketFactory(context);
            Scheme httpsScheme = new Scheme("https", 443, sf);
            SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(httpsScheme);
            ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
            HttpClient client = new DefaultHttpClient(cm);
            HttpPost post = new HttpPost("https://www.someserver.com");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用有效客户端证书时出现 HttpClient 403 错误 的相关文章

  • 不同帐户上的 Spring Boot、JmsListener 和 SQS 队列

    我正在尝试开发一个 Spring Boot 1 5 应用程序 该应用程序需要侦听来自两个不同 AWS 帐户的 SQS 队列 是否可以使用 JmsListener 注解创建监听器 我已检查权限是否正确 我可以使用 getQueueUrl 获取
  • Spring应用中Eureka健康检查的问题

    我正在开发一个基于 Spring 的应用程序 其中包含多个微服务 我的一个微服务充当尤里卡服务器 到目前为止一切正常 在我所有其他微服务中 用 EnableEurekaClient 我想启用这样的健康检查 应用程序 yml eureka c
  • 为什么 JTables 使 TableModel 在呈现时不可序列化?

    所以最近我正在开发一个工具 供我们配置某些应用程序 它不需要是什么真正令人敬畏的东西 只是一个具有一些 SQL 脚本生成功能并创建几个 XML 文件的基本工具 在此期间 我使用自己的 AbstractTableModel 实现创建了一系列
  • 为 java 游戏创建交互式 GUI

    大家好 我正在创建一个类似于 java 中的 farmville 的游戏 我只是想知道如何实现用户通常单击以与游戏客户端交互的交互式对象 按钮 我不想使用 swing 库 通用 Windows 看起来像对象 我想为我的按钮导入自定义图像 并
  • 从远程主机自动下载 X509 证书链

    我正在构建一些 net 代码 这些代码将在我们的一台服务器上按计划无人值守地运行 其执行的一部分要求它执行一个 Java 可执行文件 该可执行文件通过 SSL 与某些 Web 资源和服务进行通信 如果 Java 通过 SSL 执行某些操作并
  • Spring AspectJ 在双代理接口时失败:无法生成类的 CGLIB 子类

    我正在使用Spring的
  • Pig Udf 显示结果

    我是 Pig 的新手 我用 Java 编写了一个 udf 并且包含了一个 System out println 其中的声明 我必须知道在 Pig 中运行时该语句在哪里打印 假设你的UDF 扩展了 EvalFunc 您可以使用从返回的 Log
  • 如何获取之前的URL?

    我需要调用我的网络应用程序的 URL 例如 如果有一个从 stackoverflow com 到我的网站 foo com 的链接 我需要 Web 应用程序 托管 bean 中的 stackoverflow 链接 感谢所有帮助 谢谢 并不总是
  • 如何更改javaFX中按钮的图像?

    我正在使用javaFX 我制作了一个按钮并为此设置了图像 代码是 Image playI new Image file c Users Farhad Desktop icons play2 jpg ImageView iv1 new Ima
  • Java 公历日历更改时区

    我正在尝试设置 HOUR OF DAY 字段并更改 GregorianCalendar 日期对象的时区 GregorianCalendar date new GregorianCalendar TimeZone getTimeZone GM
  • 将 MOXy 设置为 JAXB 提供程序,而在同一包中没有属性文件

    我正在尝试使用 MOXy 作为我的 JAXB 提供程序 以便将内容编组 解组到 XML JSON 中 我创建了 jaxb properties 文件 内容如下 javax xml bind context factory org eclip
  • 经典 asp 中的 WinHttp TLS 连接

    我正在尝试将付款数据发送到 SagePay 由于他们关闭了 SSL 因此需要使用 TLS 发送数据 我的代码如下 set httpRequest Server CreateObject WinHttp WinHttprequest 5 1
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • logcat 中 mSecurityInputMethodService 为 null

    我写了一点android应显示智能手机当前位置 最后已知位置 的应用程序 尽管我复制了示例代码 并尝试了其他几种解决方案 但似乎每次都有相同的错误 我的应用程序由一个按钮组成 按下按钮应该log经度和纬度 但仅对数 mSecurityInp
  • 获取文件的总大小(以字节为单位)[重复]

    这个问题在这里已经有答案了 可能的重复 java 高效获取文件大小 https stackoverflow com questions 116574 java get file size efficiently 我有一个名为 filenam
  • Opencv Java 灰度

    我编写了以下程序 尝试从彩色转换为灰度 Mat newImage Imgcodecs imread q1 jpg Mat image new Mat new Size newImage cols newImage rows CvType C
  • 使用 svn 1.8.x、subclise 1.10 的 m2e-subclipse 连接器在哪里?

    我读到 m2e 的生产商已经停止生产 svn 1 7 以外的任何版本的 m2e 连接器 Tigris 显然已经填补了维护 m2e subclipse 连接器的空缺 Q1 我的问题是 使用 svn 1 8 x 的 eclipse 更新 url
  • 如何防止在Spring Boot单元测试中执行import.sql

    我的类路径中有一个 import sql 文件 其中包含一些 INSERT 语句 当使用 profile devel 运行我的应用程序时 它的数据被加载到 postgres 数据库中 到目前为止一切正常 当使用测试配置文件执行测试时 imp
  • Spring Boot 无法更新 azure cosmos db(MongoDb) 上的分片集合

    我的数据库中存在一个集合 documentDev 其分片键为 dNumber 样本文件 id 12831221wadaee23 dNumber 115 processed false 如果我尝试使用以下命令通过任何查询工具更新此文档 db
  • Spring Rest 和 Jsonp

    我正在尝试让我的 Spring Rest 控制器返回jsonp但我没有快乐 如果我想返回 json 但我有返回的要求 完全相同的代码可以正常工作jsonp我添加了一个转换器 我在网上找到了用于执行 jsonp 转换的源代码 我正在使用 Sp

随机推荐

  • PyDES 与 Bloomberg 数据

    我正在尝试使用 PyDES 解密 DES 编码的 Bloomberg 财务数据 该文件以 gz enc 结尾 我可以将该文件读取为二进制文件 将二进制文件重新加载回变量 该变量有数据 然后对其使用以下解密 k pyDes des passw
  • 安装OpenCV并使用GCC编译C程序

    作为我正在进行的一个更大项目的一部分 我需要在 C 程序上使用 OpenCV 库 我在 Fedora 17 32 位中使用 yum 安装了 OpenCV 和 opencv devel 我指示预处理器导入 opencv cv h 和 open
  • Jfreechart获取鼠标坐标

    我一直在尝试获取 JfreeChart 中的当前鼠标坐标 并发现以下解决方案部分有效 JFreeChart获取鼠标坐标 https stackoverflow com questions 1512112 jfreechart get mou
  • 如何打印迷宫中从源到目标的 BFS 路径

    我正在尝试实现 BFS 以便找到迷宫中从源到目标的最短路径 我遇到的问题是我无法打印路径 它在迷宫中打印为 但是如何从 BFS 的前辈中提取路径而不打印所有访问过的节点 这是我的代码供您编译 include
  • 如何避免在 PowerShell 脚本中保存用户名和密码

    所以基本上我想编写一个 Powershell 脚本 它将导出 Windows Server 备份的最后 1 天的备份日志 将信息格式化为一个漂亮的小表 然后 SMTP 将其发送到客户本地 Exchange 之外的外部位置 我有一个可以用于此
  • Python 中的协程与 Lua 中的协程相比如何?

    Lua 中对协程的支持由中的函数coroutine table https www lua org manual 5 3 manual html 2 6 主要是create resume and yield 开发人员将这些协程描述为堆栈式
  • Autoconf 子目录与子包相互依赖吗?

    我手上有一个大型项目 master 它被分成几个组件 liba b c d 以方便构建和维护 在构建整个包时 必须按顺序构建所有子组件 并且其中一些包相互依赖 更明确地说 liba 是 b c 和 d 的先决条件 并且 liba 的存在由配
  • 给定一个列表,如何仅对每两个元素满足二元谓词的子列表执行某些转换?

    在我的实际用例中 我有一个类型列表 SomeType SomeType具有有限数量的构造函数 且全部为 null 下面我将使用String代替 SomeType 并且只使用4Chars 稍微简化一下 我有一个这样的清单 aaassddddf
  • Perl:如何分割文件?

    我需要将一个文件分成不同的文件 示例 原始文件 3123123 RAW text1 text2 2312354 RAW text3 期望的输出 文件1 txt 3123123 RAW text1 text2 文件2 txt 31231235
  • git:如何将git注释添加的消息推送到中央git服务器?

    似乎没有关于 git 注释的适当文档 我使用 git Notes add 命令向其中一个提交添加了一些注释 但是当我推送提交并稍后进行单独的克隆时 我在那里看不到注释消息 有没有办法推送通过 git Notes 命令添加的所有注释消息 推送
  • Xrm.Utility.openwebresource 打开新选项卡

    我们有一个 onprem crm 2016 我只需单击功能区按钮即可打开一个 html web 资源 我在用着Xrm Utility openWebResource 问题是我们使用的是 IE11 并且所有用户的浏览器都配置为让 IE 决定如
  • 使用 XDebug 和 PHPStorm 调试 Symfony2

    我尝试着尝试 但我无法在 PHPStorm 中使用 XDebug 为 Symfony2 获得正确的调试配置 我已经检查并重新检查过 phpstorm xdebug 与 symfony2 项目 https stackoverflow com
  • 如何创建九个补丁并在我的应用程序中使用它?

    我想创建一个九补丁图像并在我的应用程序中使用它 但我不知道如何创建它 我在网上搜索了 Android 源代码 但似乎找不到任何这样的示例 我需要一个教程 以便我能够理解该过程 我已经搜索过最好和最简单的答案制作 9 块图像 现在制作 9 个
  • Rcpp 相当于 rowsum [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在寻找 R 函数的快速替代方案r
  • Python 请求:不要等待请求完成

    在 Bash 中 可以通过附加命令在后台执行命令 我怎样才能用Python做到这一点 while True data raw input Enter something requests post url data data Don t w
  • DrawContours() 不工作 opencv python

    我正在研究在 opencv python 中查找和绘制轮廓的示例 但是当我运行代码时 我只看到一个没有绘制轮廓的黑色窗口 我不知道我哪里错了 代码是 import numpy as np import cv2 im cv2 imread t
  • 如何在GAEJ中建模实体关系?

    我想知道 非常感谢一个例子 如何在 Google App Engine for Java 中建立关系建模 一对多 多对多 我在网上搜索了一下 没有发现任何关于 Java 的内容 所有指南和教程都是关于 Python 的 我由此明白了arti
  • 在 Android 中显示来自服务/接收器的“确定”对话框

    我的应用程序有一个接收器 当收到短信时会调用该接收器 我想用一个简单的一键对话框通知用户 这是我的代码 AlertDialog Builder builder new AlertDialog Builder context builder
  • 使用 Redis 作为缓存和 C# 客户端

    我是 Redis 新手 正在尝试找出一种简单的方法来使用 Redis 作为我的 C 应用程序的本地缓存 我已经下载并运行了 redis serverhttps github com MSOpenTech redis releases htt
  • 使用有效客户端证书时出现 HttpClient 403 错误

    我正在尝试使用 Java 自动执行网站上的一些任务 我有该网站的有效客户端 当我使用 Firefox 登录时有效 但当我尝试使用 http 客户端登录时 我不断收到 403 错误 请注意 我希望我的信任存储信任任何内容 我知道它不安全 但目