Play 2.6.xでサーバーがクライアント証明書を要求しないのはなぜですか?

溶ける

play-tls-exampleに従って、クライアント認証を有効にしようとしていますこれは単なる実験であるため、自己署名証明書を生成しています。

私は次のSSLエンジンプロバイダーを持っています:

package https

import java.nio.file.{FileSystems, Files}
import java.security.KeyStore

import play.core.ApplicationProvider
import play.server.api._
import javax.net.ssl._
import play.api.Configuration

class CustomSSLEngineProvider(appProvider: ApplicationProvider) extends SSLEngineProvider {

  private val config: Configuration = appProvider.current.get.configuration

  private val certificateDirectory: String = config.get[String]("certificateDirectory")

  private def readTrustInputStream(): java.io.InputStream = {
    val keyPath = FileSystems.getDefault.getPath(certificateDirectory, "clientca.jks")
    Files.newInputStream(keyPath)
  }

  private def readPassword(): Array[Char] = {
    val passwordPath = FileSystems.getDefault.getPath(certificateDirectory, "password")
    Files.readAllLines(passwordPath).get(0).toCharArray
  }

  private def readTrustManagers(): Array[TrustManager] = {
    val password = readPassword()
    val trustInputStream = readTrustInputStream()
    try {
      val keyStore = KeyStore.getInstance(KeyStore.getDefaultType)
      keyStore.load(trustInputStream, password)
      val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
      tmf.init(keyStore)
      tmf.getTrustManagers
    } finally {
      trustInputStream.close()
    }
  }

  private def readKeyInputStream(): java.io.InputStream = {
    val keyPath = FileSystems.getDefault.getPath(certificateDirectory, "localhost.jks")
    Files.newInputStream(keyPath)
  }

  private def readKeyManagers(): Array[KeyManager] = {
    val password = readPassword()
    val keyInputStream = readKeyInputStream()
    try {
      val keyStore = KeyStore.getInstance(KeyStore.getDefaultType)
      keyStore.load(keyInputStream, password)
      val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
      kmf.init(keyStore, password)

      kmf.getKeyManagers
    } finally {
      keyInputStream.close()
    }
  }

  private def createSSLContext(applicationProvider: ApplicationProvider): SSLContext = {
    val keyManagers = readKeyManagers()
    val trustManagers = readTrustManagers()

    // Configure the SSL context to use TLS
    val sslContext = SSLContext.getInstance("TLS")
    sslContext.init(keyManagers, trustManagers, null)
    sslContext
  }

  override def createSSLEngine(): SSLEngine = {

    val sslContext = createSSLContext(appProvider)

    // Start off with a clone of the default SSL parameters...
    val sslParameters = sslContext.getDefaultSSLParameters

    // Tells the server to ignore client's cipher suite preference.
    // http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#cipher_suite_preference
    sslParameters.setUseCipherSuitesOrder(true)

    // http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#SSLParameters
    val needClientAuth = true
    sslParameters.setNeedClientAuth(needClientAuth)

    // Clone and modify the default SSL parameters.
    val engine = sslContext.createSSLEngine
    engine.setSSLParameters(sslParameters)

    println(s"Need client auth: ${sslParameters.getNeedClientAuth}")

    engine
  }
}

そして、clientca.jksは次のスクリプトに従って構成されました。

#!/bin/bash

export PW=`cat password`

# Create a self signed certificate & private key to create a root certificate authority.
keytool -genkeypair -v \
  -alias clientca \
  -keystore client.jks \
  -dname "CN=clientca, OU=foo, O=bar, L=baz, ST=Ohio, C=US" \
  -keypass:env PW \
  -storepass:env PW \
  -keyalg EC \
  -keysize 256 \
  -ext KeyUsage:critical="keyCertSign" \
  -ext BasicConstraints:critical="ca:true" \
  -validity 365

# Create another key pair that will act as the client.  We want this signed by the client CA.
keytool -genkeypair -v \
  -alias client \
  -keystore client.jks \
  -dname "CN=client, OU=foo, O=bar, L=baz, ST=Ohio, C=US" \
  -keypass:env PW \
  -storepass:env PW \
  -keyalg EC \
  -keysize 256 \

# Create a certificate signing request from the client certificate.
keytool -certreq -v \
  -alias client \
  -keypass:env PW \
  -storepass:env PW \
  -keystore client.jks \
  -file client.csr

# Make clientCA create a certificate chain saying that client is signed by clientCA.
keytool -gencert -v \
  -alias clientca \
  -keypass:env PW \
  -storepass:env PW \
  -keystore client.jks \
  -infile client.csr \
  -outfile client.crt \
  -ext EKU="clientAuth" \
  -rfc

# Export the client-ca certificate from the keystore.  This goes to nginx under "ssl_client_certificate"
# and is presented in the CertificateRequest.
keytool -export -v \
  -alias clientca \
  -file clientca.crt \
  -storepass:env PW \
  -keystore client.jks \
  -rfc

# Import the signed client certificate back into client.jks.  This is important, as JSSE won't send a client
# certificate if it can't find one signed by the client-ca presented in the CertificateRequest.
keytool -import -v \
  -alias client \
  -file client.crt \
  -keystore client.jks \
  -storetype JKS \
  -storepass:env PW

# Export the client CA to pkcs12, so it's safe. 
keytool -importkeystore -v \
  -srcalias clientca \
  -srckeystore client.jks \
  -srcstorepass:env PW \
  -destkeystore client.p12 \
  -deststorepass:env PW \
  -deststoretype PKCS12

# Import the client CA's public certificate into a JKS store for Play Server to read (we don't use
# the PKCS12 because it's got the CA private key and we don't want that.
keytool -import -v \
  -alias clientca \
  -file clientca.crt \
  -keystore clientca.jks \
  -storepass:env PW << EOF
yes
EOF

# List out the contents of client.jks just to confirm it.
keytool -list -v \
  -keystore client.jks \
  -storepass:env PW

そしてmylocalhost.jksは次のスクリプトによって生成されます:

#!/bin/bash

export PW=`cat password`

# Create a server certificate, tied to localhost
keytool -genkeypair -v \
  -alias localhost \
  -dname "CN=localhost, OU=foo, O=bar, L=baz, ST=Ohio, C=US" \
  -keystore localhost.jks \
  -keypass:env PW \
  -storepass:env PW \
  -keyalg EC \
  -keysize 256 \
  -validity 385

# Create a certificate signing request for localhost
keytool -certreq -v \
  -alias localhost \
  -keypass:env PW \
  -storepass:env PW \
  -keystore localhost.jks \
  -file localhost.csr

# Tell ca to sign the localhost certificate. 
# Technically, digitalSignature for DHE or ECDHE, keyEncipherment for RSA 
keytool -gencert -v \
  -alias ca \
  -keypass:env PW \
  -storepass:env PW \
  -keystore ca.jks \
  -infile localhost.csr \
  -outfile localhost.crt \
  -ext KeyUsage:critical="digitalSignature,keyEncipherment" \
  -ext EKU="serverAuth" \
  -ext SAN="DNS:localhost" \
  -rfc

# Tell localhost.jks it can trust ca as a signer.
keytool -import -v \
  -alias ca \
  -file ca.crt \
  -keystore localhost.jks \
  -storetype JKS \
  -storepass:env PW << EOF
yes
EOF

# Import the signed certificate back into localhost.jks 
keytool -import -v \
  -alias localhost \
  -file localhost.crt \
  -keystore localhost.jks \
  -storetype JKS \
  -storepass:env PW

そして、次の関連する構成で本番環境で実行する場合:

http.port=disabled 
https.port = 9443 
play.server.https.engineProvider=https.CustomSSLEngineProvider 
certificateDirectory=/path/to/certs/ 
play.server.https.keyStore.path=/path/to/certs/localhost.jks 
play.server.https.keyStore.password=`cat /path/to/certs/password` # actual string
jdk.tls.rejectClientInitiatedRenegotiation=true

安全でないcurlを発行すると、サーバーがクライアント証明書を要求しないことがわかりましたcurl -k https://localhost:9443::

13:35:13.173 [application-akka.actor.default-dispatcher-4] INFO akka.event.slf4j.Slf4jLogger - Slf4jLogger started
13:35:13.182 [application-akka.actor.default-dispatcher-4] DEBUG akka.event.EventStream - logger log1-Slf4jLogger started
13:35:13.185 [application-akka.actor.default-dispatcher-4] DEBUG akka.event.EventStream - Default Loggers started
13:35:13.213 [main] DEBUG play.api.libs.concurrent.ActorSystemProvider - Starting application default Akka system: application
13:35:13.368 [main] DEBUG controllers.AssetsConfiguration - Using the following cache configuration for assets:
     enableCaching = true
     enableCacheControl = true
     defaultCacheControl = public, max-age=3600
     aggressiveCacheControl = public, max-age=31536000, immutable
     configuredCacheControl:


13:35:13.414 [main] INFO play.api.Play - Application started (Prod)
13:35:13.678 [application-akka.actor.default-dispatcher-2] DEBUG com.typesafe.sslconfig.akka.AkkaSSLConfig - Initializing AkkaSSLConfig extension...
13:35:13.680 [application-akka.actor.default-dispatcher-2] DEBUG com.typesafe.sslconfig.akka.AkkaSSLConfig - buildHostnameVerifier: created hostname verifier: com.typesafe.sslconfig.ssl.DefaultHostnameVerifier@4acf72b6
13:35:14.046 [application-akka.actor.default-dispatcher-3] DEBUG akka.io.TcpListener - Successfully bound to /0:0:0:0:0:0:0:0:9443
13:35:14.054 [main] INFO play.core.server.AkkaHttpServer - Listening for HTTPS on /0:0:0:0:0:0:0:0:9443
13:35:20.420 [application-akka.actor.default-dispatcher-3] DEBUG akka.io.TcpListener - New connection accepted
Need client auth: true
13:35:20.597 [application-akka.actor.default-dispatcher-3] DEBUG akka.stream.impl.io.TLSActor - closing output

サーバークライアント認証を必要としているにもかかわらず、クライアントが証明書の入力を求められることはなく、安全でない接続を正常に開始します。なんでこんなことが起こっているの?

溶ける

これに関連する未解決の問題があります。

これを機能させるPlayAkkaHttp2Supportには、クライアント認証を実行しようとするプロジェクトでsbtを有効にする必要があり、JDK161の問題を回避するためにJavaエージェントを更新する必要があります。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

.ipaをエクスポートするXcode 6ベータ2の問題:「アカウントにはすでに有効なiOS配布証明書があります」

分類Dev

perl6 replが2つの異なるクラスを区別しないのはなぜですか?

分類Dev

サブスクライバーがAngular2 / 4/6で完了しなかった場合のreturnステートメントの待機方法

分類Dev

Linuxでmode = 6のボンディングを使用すると、2つのサーバーが同じNICに接続するのはなぜですか?

分類Dev

Androidが間違ったSSL証明書を取得するのはなぜですか?(2つのドメイン、1つのサーバー)

分類Dev

Play Framework 2.xアクションでMongoDB非同期Javaドライバーを使用するにはどうすればよいですか?

分類Dev

iPhone6が@ 2x画像アセットを使用するのはなぜですか?

分類Dev

Google Maps v2は、Playサービスのない2.2デバイスでは使用できませんか?

分類Dev

自己署名証明書を使用したAndroid9でSSLPeerUnverifiedExceptionホスト名196.1X.3X.X2が検証されていないエラーが発生しましたが、他のすべてのバージョンで機能します

分類Dev

6TBハードドライブが2つの未割り当てパーティションとして表示されるのはなぜですか?

分類Dev

OpenSSH 6.xクライアントが接続時に文字列を送信するのに、5.xは送信しないのはなぜですか?

分類Dev

CASオーバーレイテンプレートブランチ6.xがビルドツールとしてMavenをサポートしないのはなぜですか?

分類Dev

WSO2 IS 5.10.0でサービスプロバイダーの「クライアントシークレットなしで認証を許可する」をプログラムで構成するにはどうすればよいですか?

分類Dev

intellijでPlay 2テンプレートを作成できない:Java Play Framework

分類Dev

クライアントで証明書をデコードできません新しいX509Certificate2()

分類Dev

unclass()関数を使用する目的は何ですか?また、「3,4,5,6,7,8,9,10ではなく、正の場合、列インデックスは最大2でなければならない」というエラーが表示される理由

分類Dev

プライマリドメインを備えたNginx80は正常に機能しますが、サブドメインを備えたApache2 8080が機能しないのはなぜですか(80ポートからの400の不正な要求)?

分類Dev

CPUが100%のときに、ロードバランサーが使用可能なec2にリダイレクトされないのはなぜですか?

分類Dev

Google Playサービスのバージョンが正しくないのはなぜですか?

分類Dev

JavaScript ES6がマルチコンストラクタクラスをサポートしないのはなぜですか?

分類Dev

gitエラーを解決する方法:サーバーはアドバタイズされていないオブジェクト3a2ceef391af73994dfeb0d8ef57ed6a52ef4238のリクエストを許可しませんか?

分類Dev

サービス0x2cでInt0x21を使用すると、プログラマブルインターバルタイマーが正しい時間値を表示しないのはなぜですか

分類Dev

HTTP2でサーバー送信イベントを使用する場合、まだ実用的な6接続制限がありますか?

分類Dev

Play Framework 2の「テスト」設定を変更して完全なスタックトレースを表示するにはどうすればよいですか?

分類Dev

NICが次のように2つのIPv6アドレスを取得したのはなぜですか?

分類Dev

Dialogflowが同じフォローアップインテントを2回要求しているのはなぜですか?

分類Dev

2つの同じレコードを挿入しても、トランザクションがロールバックしないのはなぜですか

分類Dev

digが適切なIPv6DNSサーバーを使用しないのはなぜですか?

分類Dev

httpsを使用してのみアクセスできるロードバランサーのec2インスタンス内にnginxがある場合、nginx自体に証明書を設定する必要がありますか?

Related 関連記事

  1. 1

    .ipaをエクスポートするXcode 6ベータ2の問題:「アカウントにはすでに有効なiOS配布証明書があります」

  2. 2

    perl6 replが2つの異なるクラスを区別しないのはなぜですか?

  3. 3

    サブスクライバーがAngular2 / 4/6で完了しなかった場合のreturnステートメントの待機方法

  4. 4

    Linuxでmode = 6のボンディングを使用すると、2つのサーバーが同じNICに接続するのはなぜですか?

  5. 5

    Androidが間違ったSSL証明書を取得するのはなぜですか?(2つのドメイン、1つのサーバー)

  6. 6

    Play Framework 2.xアクションでMongoDB非同期Javaドライバーを使用するにはどうすればよいですか?

  7. 7

    iPhone6が@ 2x画像アセットを使用するのはなぜですか?

  8. 8

    Google Maps v2は、Playサービスのない2.2デバイスでは使用できませんか?

  9. 9

    自己署名証明書を使用したAndroid9でSSLPeerUnverifiedExceptionホスト名196.1X.3X.X2が検証されていないエラーが発生しましたが、他のすべてのバージョンで機能します

  10. 10

    6TBハードドライブが2つの未割り当てパーティションとして表示されるのはなぜですか?

  11. 11

    OpenSSH 6.xクライアントが接続時に文字列を送信するのに、5.xは送信しないのはなぜですか?

  12. 12

    CASオーバーレイテンプレートブランチ6.xがビルドツールとしてMavenをサポートしないのはなぜですか?

  13. 13

    WSO2 IS 5.10.0でサービスプロバイダーの「クライアントシークレットなしで認証を許可する」をプログラムで構成するにはどうすればよいですか?

  14. 14

    intellijでPlay 2テンプレートを作成できない:Java Play Framework

  15. 15

    クライアントで証明書をデコードできません新しいX509Certificate2()

  16. 16

    unclass()関数を使用する目的は何ですか?また、「3,4,5,6,7,8,9,10ではなく、正の場合、列インデックスは最大2でなければならない」というエラーが表示される理由

  17. 17

    プライマリドメインを備えたNginx80は正常に機能しますが、サブドメインを備えたApache2 8080が機能しないのはなぜですか(80ポートからの400の不正な要求)?

  18. 18

    CPUが100%のときに、ロードバランサーが使用可能なec2にリダイレクトされないのはなぜですか?

  19. 19

    Google Playサービスのバージョンが正しくないのはなぜですか?

  20. 20

    JavaScript ES6がマルチコンストラクタクラスをサポートしないのはなぜですか?

  21. 21

    gitエラーを解決する方法:サーバーはアドバタイズされていないオブジェクト3a2ceef391af73994dfeb0d8ef57ed6a52ef4238のリクエストを許可しませんか?

  22. 22

    サービス0x2cでInt0x21を使用すると、プログラマブルインターバルタイマーが正しい時間値を表示しないのはなぜですか

  23. 23

    HTTP2でサーバー送信イベントを使用する場合、まだ実用的な6接続制限がありますか?

  24. 24

    Play Framework 2の「テスト」設定を変更して完全なスタックトレースを表示するにはどうすればよいですか?

  25. 25

    NICが次のように2つのIPv6アドレスを取得したのはなぜですか?

  26. 26

    Dialogflowが同じフォローアップインテントを2回要求しているのはなぜですか?

  27. 27

    2つの同じレコードを挿入しても、トランザクションがロールバックしないのはなぜですか

  28. 28

    digが適切なIPv6DNSサーバーを使用しないのはなぜですか?

  29. 29

    httpsを使用してのみアクセスできるロードバランサーのec2インスタンス内にnginxがある場合、nginx自体に証明書を設定する必要がありますか?

ホットタグ

アーカイブ