java - X.509 证书不完整 : SubjectAlternativeName extension MUST be marked critical when subject field is empty

标签 java httpclient x509

我有一个基于用java编写的“commons-httpclient”(v3.*)的httpclient客户端可以与至少两个不同的产品(服务器)正常工作。

但是与我希望它能够使用的新服务器(产品)的socket连接失败。

这是一个堆栈跟踪:

result = {javax.net.ssl.SSLProtocolException@4375} Method threw 'javax.net.ssl.SSLProtocolException' exception.
 detailMessage = "X.509 Certificate is incomplete: SubjectAlternativeName extension MUST be marked critical when subject field is empty"
 cause = {java.security.cert.CertificateParsingException@4379} "java.security.cert.CertificateParsingException: X.509 Certificate is incomplete: SubjectAlternativeName extension MUST be marked critical when subject field is empty"
  detailMessage = "X.509 Certificate is incomplete: SubjectAlternativeName extension MUST be marked critical when subject field is empty"
  cause = {java.security.cert.CertificateParsingException@4379} "java.security.cert.CertificateParsingException: X.509 Certificate is incomplete: SubjectAlternativeName extension MUST be marked critical when subject field is empty"
  stackTrace = {java.lang.StackTraceElement[71]@4518} 
   0 = {java.lang.StackTraceElement@4520} "sun.security.x509.X509CertInfo.verifyCert(X509CertInfo.java:744)"
   1 = {java.lang.StackTraceElement@4521} "sun.security.x509.X509CertInfo.parse(X509CertInfo.java:706)"
   2 = {java.lang.StackTraceElement@4522} "sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:167)"
   3 = {java.lang.StackTraceElement@4523} "sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1804)"
   4 = {java.lang.StackTraceElement@4524} "sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:195)"
   5 = {java.lang.StackTraceElement@4525} "sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:102)"
   6 = {java.lang.StackTraceElement@4526} "java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)"
   7 = {java.lang.StackTraceElement@4527} "sun.security.ssl.HandshakeMessage$CertificateMsg.<init>(HandshakeMessage.java:449)"
   8 = {java.lang.StackTraceElement@4528} "sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)"
   9 = {java.lang.StackTraceElement@4529} "sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)"
   10 = {java.lang.StackTraceElement@4530} "sun.security.ssl.Handshaker.process_record(Handshaker.java:961)"
   11 = {java.lang.StackTraceElement@4531} "sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)"
   12 = {java.lang.StackTraceElement@4532} "sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)"
   13 = {java.lang.StackTraceElement@4533} "sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:757)"
   14 = {java.lang.StackTraceElement@4534} "sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)"
   15 = {java.lang.StackTraceElement@4535} "java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)"
   16 = {java.lang.StackTraceElement@4536} "java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)"
   17 = {java.lang.StackTraceElement@4537} "org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:828)"
   18 = {java.lang.StackTraceElement@4538} "org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2116)"
   19 = {java.lang.StackTraceElement@4539} "org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)"
   20 = {java.lang.StackTraceElement@4540} "org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)"
   21 = {java.lang.StackTraceElement@4541} "org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)"
   22 = {java.lang.StackTraceElement@4542} "org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)"
   23 = {java.lang.StackTraceElement@4543} "org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)"
   24 = {java.lang.StackTraceElement@4544} "com.radware.utils.https.HttpSessionBase.sendHttpMethod(HttpSessionBase.java:59)"
   25 = {java.lang.StackTraceElement@4545} "com.radware.restcore.utils.retry.RetryRequestData.executeRequest(RetryRequestData.java:30)"
   26 = {java.lang.StackTraceElement@4546} "com.radware.restcore.RestClientOperations.innerSendRequest(RestClientOperations.java:228)"
   27 = {java.lang.StackTraceElement@4547} "com.radware.restcore.RestClientOperations.runCommand(RestClientOperations.java:129)"
   28 = {java.lang.StackTraceElement@4548} "com.radware.restcore.RestClientOperations.runCommand(RestClientOperations.java:96)"
   29 = {java.lang.StackTraceElement@4549} "com.radware.restcore.RestClientOperations.getCommand(RestClientOperations.java:63)"
   30 = {java.lang.StackTraceElement@4550} "com.radware.restcore.utils.impl.RestClientImpl.innerRestRequest(RestClientImpl.java:14)"
   31 = {java.lang.StackTraceElement@4551} "com.radware.rest.testhandlers.RestHandler.executeBasicRest(RestHandler.java:32)"
   32 = {java.lang.StackTraceElement@4552} "com.radware.rest.testhandlers.controllerManager.ApplicationHandler.getAllApplications(ApplicationHandler.java:64)"
   33 = {java.lang.StackTraceElement@4553} "com.radware.tests.resttests.ApplicationManagerTests.getAllApplications(ApplicationManagerTests.java:133)"
   34 = {java.lang.StackTraceElement@4554} "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)"
   35 = {java.lang.StackTraceElement@4555} "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)"
   36 = {java.lang.StackTraceElement@4556} "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)"
   37 = {java.lang.StackTraceElement@4557} "java.lang.reflect.Method.invoke(Method.java:498)"
   38 = {java.lang.StackTraceElement@4558} "cucumber.runtime.Utils$1.call(Utils.java:40)"
   39 = {java.lang.StackTraceElement@4559} "cucumber.runtime.Timeout.timeout(Timeout.java:16)"
   40 = {java.lang.StackTraceElement@4560} "cucumber.runtime.Utils.invoke(Utils.java:34)"
   41 = {java.lang.StackTraceElement@4561} "cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:38)"
   42 = {java.lang.StackTraceElement@4562} "cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java:37)"
   43 = {java.lang.StackTraceElement@4563} "cucumber.runtime.Runtime.runStep(Runtime.java:300)"
   44 = {java.lang.StackTraceElement@4564} "cucumber.runtime.model.StepContainer.runStep(StepContainer.java:81)"
   45 = {java.lang.StackTraceElement@4565} "cucumber.runtime.model.StepContainer.runSteps(StepContainer.java:70)"
   46 = {java.lang.StackTraceElement@4566} "cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:44)"
   47 = {java.lang.StackTraceElement@4567} "cucumber.runtime.junit.ExecutionUnitRunner.run(ExecutionUnitRunner.java:102)"
   48 = {java.lang.StackTraceElement@4568} "cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:85)"
   49 = {java.lang.StackTraceElement@4569} "cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:28)"
   50 = {java.lang.StackTraceElement@4570} "org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)"
   51 = {java.lang.StackTraceElement@4571} "org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)"
   52 = {java.lang.StackTraceElement@4572} "org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)"
   53 = {java.lang.StackTraceElement@4573} "org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)"
   54 = {java.lang.StackTraceElement@4574} "org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)"
   55 = {java.lang.StackTraceElement@4575} "org.junit.runners.ParentRunner.run(ParentRunner.java:363)"
   56 = {java.lang.StackTraceElement@4576} "cucumber.runtime.junit.FeatureRunner.run(FeatureRunner.java:92)"
   57 = {java.lang.StackTraceElement@4577} "cucumber.api.junit.Cucumber.runChild(Cucumber.java:247)"
   58 = {java.lang.StackTraceElement@4578} "cucumber.api.junit.Cucumber.runChild(Cucumber.java:49)"
   59 = {java.lang.StackTraceElement@4579} "org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)"
   60 = {java.lang.StackTraceElement@4580} "org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)"
   61 = {java.lang.StackTraceElement@4581} "org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)"
   62 = {java.lang.StackTraceElement@4582} "org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)"
   63 = {java.lang.StackTraceElement@4583} "org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)"
   64 = {java.lang.StackTraceElement@4584} "org.junit.runners.ParentRunner.run(ParentRunner.java:363)"
   65 = {java.lang.StackTraceElement@4585} "cucumber.api.junit.Cucumber.run(Cucumber.java:252)"
   66 = {java.lang.StackTraceElement@4586} "org.junit.runner.JUnitCore.run(JUnitCore.java:137)"
   67 = {java.lang.StackTraceElement@4587} "com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)"
   68 = {java.lang.StackTraceElement@4588} "com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)"
   69 = {java.lang.StackTraceElement@4589} "com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)"
   70 = {java.lang.StackTraceElement@4590} "com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)"
  suppressedExceptions = {java.util.Collections$UnmodifiableRandomAccessList@4381}  size = 0
 stackTrace = {java.lang.StackTraceElement[64]@4380} 
 suppressedExceptions = {java.util.Collections$UnmodifiableRandomAccessList@4381}  size = 0

这是构建 SSLContext 的方法:

private static SSLContext createEasySSLContext() {
    try {
        TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
        SSLContext context = SSLContexts.custom().loadTrustMaterial(acceptingTrustStrategy).build();
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
        context.init(null, new TrustManager[] { new TrustAllTrustManager() }, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        return context;
    } catch (Exception e) {
        LOG.error(e.getMessage(), e);
        throw new HttpClientError(e.toString());
    }
}

我得到的一个异常(exception):

Connection has been shutdown: javax.net.ssl.SSLProtocolException: X.509 Certificate is incomplete: SubjectAlternativeName extension MUST be marked critical when subject field is empty .

最佳答案

Subject 字段为空且 SAN 扩展不重要时,预计会出现此错误。引用自RFC 5280 §4.2.1.6 :

If the subject field contains an empty sequence, then the issuing CA MUST include a subjectAltName extension that is marked as critical.

它符合 RFC 标准。要解决此问题,您需要获取具有非空 Subject 字段或关键 SAN 扩展的正确证书。

关于java - X.509 证书不完整 : SubjectAlternativeName extension MUST be marked critical when subject field is empty,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56168165/

相关文章:

c# - 如何模拟/创建 X509Certificate2 进行单元测试?

java - 清除ArrayList并在适配器ListView中从 fragment 执行notifyDataSetChanged

java - 使用 JavaCompiler 编译目录

c - 使用套接字的 Http 客户端程序无法正常工作

java - 如何为 apache http 客户端中的所有请求设置默认 header ?

c# - 在 C# 中以编程方式将 .crt + .key 文件转换为 X509Certificate2

java - 为每个传入请求重置 servlet 类的实例变量

c# - 如何将该运算符 C# 代码表示为 java?

java - 使用 Apache HTTPAsyncClient 针对每个 HTTPS 请求自定义 SSLContext

java - x509认证失败时重定向循环