【问题标题】:Using client certificates with twitter finagle将客户端证书与 twitter finagle 一起使用
【发布时间】:2015-06-09 10:39:51
【问题描述】:

我的服务器使用 TLSv1.2 并且需要客户端证书才能连接。我可以使用 CURL 向服务器发送请求(此请求工作正常):

curl --data "SAMPLETEXT" https://myserver.com/webservice --insecure --key privkey.pem --cert certificate.cert

(是的,服务器有自签名证书并且需要--insecure 标志;不,我无法解决这个问题)。 现在,我想创建客户端以从 Scala 代码发送请求。 MyClient 是包含所需密码和路径的对象。为此,我创建了SSLContext:

  private val keyStore = {
    //Setting up BouncyCastle provider for message signing
    Security.addProvider(new BouncyCastleProvider())
    //Loading keystore from specified file
    val clientStore = KeyStore.getInstance("JKS")
    val inputStream = new FileInputStream(MyClient.keystore)
    clientStore.load(inputStream, MyClient.keystorePassword.toCharArray)
    inputStream.close()
    clientStore
  }

  //Retrieving certificate and key
  private val cert = keyStore.getCertificate(MyClient.keyAlias).asInstanceOf[X509Certificate]
  private val key = keyStore.getKey(MyClient.keyAlias, MyClient.keystorePassword.toCharArray).asInstanceOf[PrivateKey]

  //Creating SSL context
  private val sslContext = {
    val context = SSLContext.getInstance("TLS")
    val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
    val kmf: KeyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
    kmf.init(keyStore, MyClient.keystorePassword.toCharArray)
    tmf.init(keyStore)
    context.init(kmf.getKeyManagers, tmf.getTrustManagers, null)
    context
  }

然后用它来构建客户端:

  private val httpClient =
  richHttpBuilder(HttpEndpoint(baseUri))
    .hostConnectionLimit(1)
    .tlsWithoutValidation()
    .tls(sslContext, Some(MyClient.host))
    .build()

但我仍然收到错误:

future 返回了一个异常类型: com.twitter.finagle.ChannelWriteException,带有消息: com.twitter.finagle.SslHandshakeException:一般 SSLEngine 问题 在远程地址:

我做错了什么?

【问题讨论】:

    标签: scala ssl curl


    【解决方案1】:

    我花了一周的时间才意识到自己做错了什么。

    选项 .tlsWithoutValidation().tls(sslContext, Some(MyClient.host)) 不能同时使用,因为它们配置了构建器的相同属性 (Transport.TLSClientEngine)。

    有三种解决方案。

    1. 使用正确的服务器证书。不幸的是,这个不适用。

    2. 将服务器证书添加到密钥库。它将被标记为受信任,并且客户端将在没有tlsWithoutValidation 的情况下愉快地工作。

    3. 使用不验证任何内容的无知信任管理器:

        private[this] class IgnorantTrustManager extends X509TrustManager {
          def getAcceptedIssuers(): Array[X509Certificate] = new Array[X509Certificate](0)
          def checkClientTrusted(certs: Array[X509Certificate], authType: String) {
          }
          def checkServerTrusted(certs: Array[X509Certificate], authType: String) {
          }
        }
      

      然后将其用作信任管理器:

      context.init(kmf.getKeyManagers, new IgnorantTrustManager(), null)
      

      tlsWithoutValidation 选项必须删除:

        richHttpBuilder(HttpEndpoint(baseUri))
          .hostConnectionLimit(1)
          .tls(sslContext, Some(YandexClient.host))
          .build()
      

      此解决方案消除了证书的全部用途,因此仅应用于测试。

    【讨论】:

      猜你喜欢
      • 2010-12-24
      • 2013-01-19
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      • 1970-01-01
      • 1970-01-01
      • 2020-01-23
      • 1970-01-01
      相关资源
      最近更新 更多