收到致命警报:unknown_ca,同时进行相互身份验证

时间:2010-12-06 04:34:27

标签: java ssl spring-ws

我正在开发一个Web服务客户端,它需要与启用了相互身份验证的服务器进行通信。

我已完成以下步骤。

  1. 将服务器证书(自签名)添加到信任库,并使用HttpsURLConnection将其设置为SSLSocketFactory
  2. 将客户端证书(CA签名)提供给服务器管理员,以将其添加到其受信任的商店。
  3. 通过导入客户端证书创建了一个密钥库,并创建了一个密钥管理器来“HttpsURLConnection”。
  4. 当我尝试运行此示例时,我得到一个例外

    org.springframework.ws.soap.axiom.AxiomSoapMessageException: Could not write message to OutputStream: java.net.SocketException: Software caused connection abort: recv failed; nested exception is javax.xml.stream.XMLStreamException: java.net.SocketException: Software caused connection abort: recv failed
            at org.springframework.ws.soap.axiom.AxiomSoapMessage.writeTo(AxiomSoapMessage.java:261)
            at org.springframework.ws.transport.AbstractWebServiceConnection.send(AbstractWebServiceConnection.java:45)
            at org.springframework.ws.client.core.WebServiceTemplate.sendRequest(WebServiceTemplate.java:586)
            at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:549)
            at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:502)
            at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:480)
            at test.SamlTest.request(SamlTest.java:29)
            at test.SamlTest.main(SamlTest.java:63)
        Caused by: javax.xml.stream.XMLStreamException: java.net.SocketException: Software caused connection abort: recv failed
            at com.sun.xml.internal.stream.writers.XMLStreamWriterImpl.writeStartDocument(Unknown Source)
            at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.internalSerialize(SOAPEnvelopeImpl.java:193)
            at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:756)
            at org.apache.axiom.soap.impl.llom.SOAPMessageImpl.internalSerialize(SOAPMessageImpl.java:71)
            at org.apache.axiom.om.impl.llom.OMDocumentImpl.internalSerialize(OMDocumentImpl.java:324)
            at org.apache.axiom.om.impl.llom.OMDocumentImpl.serialize(OMDocumentImpl.java:375)
            at org.springframework.ws.soap.axiom.AxiomSoapMessage.writeTo(AxiomSoapMessage.java:252)
            ... 7 more
        Caused by: java.net.SocketException: Software caused connection abort: recv failed
            at java.net.SocketInputStream.socketRead0(Native Method)
            at java.net.SocketInputStream.read(Unknown Source)
            at com.sun.net.ssl.internal.ssl.InputRecord.readFully(Unknown Source)
            at com.sun.net.ssl.internal.ssl.InputRecord.readV3Record(Unknown Source)
            at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
            at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
            at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
            at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
            at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
            at org.springframework.ws.transport.http.HttpUrlConnection.getRequestOutputStream(HttpUrlConnection.java:81)
            at org.springframework.ws.transport.AbstractSenderConnection$RequestTransportOutputStream.createOutputStream(AbstractSenderConnection.java:101)
            at org.springframework.ws.transport.TransportOutputStream.getOutputStream(TransportOutputStream.java:41)
            at org.springframework.ws.transport.TransportOutputStream.write(TransportOutputStream.java:64)
            at com.sun.xml.internal.stream.writers.UTF8OutputStreamWriter.write(Unknown Source)
            at com.sun.xml.internal.stream.writers.UTF8OutputStreamWriter.write(Unknown Source)
            ... 14 more
    

    我错过了什么?

    已更新

    启用jvm log后找到日志

    trigger seeding of SecureRandom
        done seeding SecureRandom
        %% No cached client session
        *** ClientHello, TLSv1
        RandomCookie:  GMT: 1274794757 bytes = { 250, 192, 120, 159, 84, 244, 96, 103, 128, 221, 36, 200, 229, 95, 84, 152, 179, 202, 161, 56, 95, 161, 234, 136, 128, 52, 45, 228 }
        Session ID:  {}
        Compression Methods:  { 0 }
        ***
        main, WRITE: TLSv1 Handshake, length = 73
        main, WRITE: SSLv2 client hello message, length = 98
        main, READ: TLSv1 Handshake, length = 74
        *** ServerHello, TLSv1
        Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
        Compression Method: 0
        ***
        %% Created:  [Session-1, SSL_RSA_WITH_RC4_128_MD5]
        ** SSL_RSA_WITH_RC4_128_MD5
        main, READ: TLSv1 Handshake, length = 976
        *** Certificate chain
        chain [0] = [
        [
          Version: V3
          Subject: EMAILADDRESS=email@email.com, CN=email@email.com, OU=MyOU, O=xyz
          Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4
    
          Key:  Sun RSA public key, 1024 bits
          public exponent: 65537
          Validity: [From: Tue Jul 18 02:30:07 IST 2006,
                       To: Mon Jul 13 02:30:07 IST 2026]
          Issuer: EMAILADDRESS=email@email.com, CN=email@email.com, OU=MyOU, O=xyz
          SerialNumber: [   ]
    
        Certificate Extensions: 3
        [1]: ObjectId: 2.5.29.14 Criticality=false
        SubjectKeyIdentifier [
        KeyIdentifier [
        ]
        ]
    
        [2]: ObjectId: 2.5.29.35 Criticality=false
        AuthorityKeyIdentifier [
        KeyIdentifier [
        ]
    
        [EMAILADDRESS=email@email.com, CN=email@email.com, OU=MyOU, O=xyz]
        SerialNumber: [    ecbcae10 2ba4c279]
        ]
    
        [3]: ObjectId: 2.5.29.19 Criticality=false
        BasicConstraints:[
          CA:true
          PathLen:2147483647
        ]
    
        ]
          Algorithm: [MD5withRSA]
          Signature:
    
        ]
        ***
        main, SEND TLSv1 ALERT:  fatal, description = certificate_unknown
        main, WRITE: TLSv1 Alert, length = 2
        main, called closeSocket()
        main, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
            at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
            at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
            at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
            at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
            at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
            at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
            at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
            at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
            at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
            at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
            at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
            at com.arun.test.http.TiMutualAuthClient.main(TiMutualAuthClient.java:71)
        Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
            at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
            at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
            at sun.security.validator.Validator.validate(Unknown Source)
            at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
            at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
            at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
            ... 13 more
        Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
            at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
            at java.security.cert.CertPathBuilder.build(Unknown Source)
            ... 19 more
    

    谢谢

3 个答案:

答案 0 :(得分:5)

客户端密钥库是否包含私钥条目?从您的描述中不清楚。还不清楚unknown_ca的来源:它不会出现在堆栈跟踪中。最好使用-Djavax.net.debug = ssl运行客户端,握手并发布结果。

答案 1 :(得分:2)

我认为问题出在我使用的客户证书上。它具有以下扩展值集

  

证书密钥用法
  关键
  签约
  不可否认
  关键加密
  数据加密   

  扩展密钥用法
  不重要的是   TLS Web服务器认证(1.3.6.1.5.5.7.3.1)
  TLS Web客户端身份验证(1.3.6.1.5.5.7.3.2)

一旦我创建了一个没有任何扩展名的自签名证书并将其用作我的客户端证书,它就可以正常工作。

答案 2 :(得分:0)

您需要将认证用户的CA的公钥(或用户自己的公钥,如果它是他们正在使用的自我认证的密钥)放入服务器的密钥库中。否则,服务器根本不知道用户的证书是真实的还是由冒充他们的人呈现。提前获得证书可以使服务器理解身份并信任它(SSL协议需要将其作为防止琐碎的中间人攻击的一部分)。