草庐IT

java - SSL 证书验证 : javax.net.ssl.SSLHandshakeException

coder 2024-03-09 原文

我正在尝试通过 Jersey Client 调用 HTTPS REST API。在开发过程中,我偶然发现了以下错误:

Exception in thread "main" com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching mvn.signify.abc.com found
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:149)
    at com.sun.jersey.api.client.Client.handle(Client.java:648)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:670)
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:503)
    at com.lftechnology.sbworkbench.utility.utils.PingFederateUtility.main(PingFederateUtility.java:32)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching mvn.signify.abc.com found

所以我在谷歌上搜索了一下,找到了大量的解决方案,这些解决方案确实有效。

  1. HTTPS using Jersey Client
  2. https://gist.github.com/outbounder/1069465
  3. How to fix the "java.security.cert.CertificateException: No subject alternative names present" error?
  4. http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/
  5. http://java.globinch.com/enterprise-java/security/fix-java-security-certificate-exception-no-matching-localhost-found/

他们在不同的领域,但他们有一个共同的解决方案来解决这个问题。

场景

我目前在开发环境中使用自己创建的自签名证书。因此它必然会显示问题。

问题

上述解决方案侧重于跳过/允许验证所有证书。

但是当我将其移至生产环境时,我便可以从可靠来源访问有效签名证书。

  1. 那么这些解决方案对我投入生产有帮助吗?
  2. 可以跳过 SSL 验证吗?
  3. 实现通用解决方案的其他替代方法是什么 开发和生产环境?

附言

我使用的解决方案是,

try
{
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkClientTrusted(X509Certificate[] certs, String authType) {
        }
        public void checkServerTrusted(X509Certificate[] certs, String authType) {
        }
    }
    };

    // Install the all-trusting trust manager
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

    // Create all-trusting host name verifier
    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    // Install the all-trusting host verifier
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
} catch (KeyManagementException e) {
    e.printStackTrace();
}

然后我与 Jersey 合作使其工作。而且效果很好。

所以,问题 又来了。 此解决方案是否适合在生产环境中使用? 但是,您不想修改返回的实体,最好以只读模式获取实体。这将允许 Hibernate 丢弃脏检查机制用来检测实体状态修改的关联分离状态。刷新期间会跳过更多只读实体。

最佳答案

I am currently using a self created self-signed certificate in development environment. ... javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching dev.ppc.lftechnology.com found

看来自签名证书不正确。

下面是我用来创建自签名证书和证书请求以在测试期间使用的 OpenSSL CONF 文件。将其保存为 example-com.conf。根据您的喜好更改 [ alternate_names ] 下的 DNS 名称。您甚至可以将 localhostlocalhost.localdomain127.0.0.1 放在那里进行测试。

如果要创建自签名证书,请使用:

openssl req -config example-com.conf -new -x509 -newkey rsa:2048 \
    -nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem

如果您想创建一个由受信任的机构签署的签名请求 (CSR),请使用:

openssl req -config example-com.conf -new -newkey rsa:2048 \
    -nodes -keyout example-com.key.pem -days 365 -out example-com.req.pem

自签名证书和签名请求之间的区别在于 -x509 选项。在存在 -x509 的情况下,将创建一个自签名证书。缺少 -x509 表示已创建请求。

如果您想打印您的自签名证书或请求查看其中的实际内容,请使用:

openssl x509 -in example-com.cert.pem -text -noout
openssl req -in example-com.req.pem -text -noout

如果你想测试服务器,那么使用s_client:

openssl s_client -connect <server>:<port> -CAfile <trust-anchor.pem>

上面的命令应该以类似于Verify OK (0) 的消息结束。如果您没有收到 Verify OK (0),请修复您的测试装置。 OpenSSL 成功完成后,这将成为您的基准。


[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_extensions
x509_extensions     = cert_extensions
string_mask         = utf8only

[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = NY

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here. Its presented to the user.
#   The server's DNS name show up in Subject Alternate Names. Plus, 
#   DNS names here is deprecated by both IETF and CA/Browser Forums.
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = test@example.com

[ cert_extensions ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier  = keyid,issuer

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
# extendedKeyUsage  = serverAuth
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

[ req_extensions ]

subjectKeyIdentifier        = hash

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
# extendedKeyUsage  = serverAuth
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

Is it OK to skip SSL verification ?

没有。这是非常不负责任的。如果您不打算正确使用 PKIX,那为什么还要使用它呢?

我想到了:The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software .


HostnameVerifier allHostsValid = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

最好将您的自签名证书加载到 keystore 中(或加载您的私有(private) CA),然后将其传递给 SSLContext.init。然后一切都按预期工作,并且无需信任一切或从 verify 返回 true

Bruno 和 EJP 对这个主题有很多答案。


What are the other alternate way to achieve a common solution for both development and production environment?

使用格式正确的证书链接回受信任的根。

为了测试,您可以创建一个自签名证书。或者,创建证书请求并让您的内部 CA 在私有(private) PKI 中对其进行签名。在这种情况下,您需要信任您的自签名证书或信任您的内部 CA。

对于生产,您可以使用由 CA Zoo 的一名成员签署的证书,以便组织外的其他人也信任它。 StartComCACert提供免费的 1 类证书。

1 类证书通常经过域验证并且不允许通配符。虽然 1 类是免费签发的,但他们会收取撤销费用,因为这是成本所在。

如果您需要外卡,那么您通常会购买 2 级或更高级别的。

关于java - SSL 证书验证 : javax.net.ssl.SSLHandshakeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25079751/

有关java - SSL 证书验证 : javax.net.ssl.SSLHandshakeException的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  4. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  5. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  6. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  7. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  8. ruby-on-rails - 如何将验证与模型分开 - 2

    我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:

  9. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  10. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

随机推荐