Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 为什么不是';我的服务器是否在Play 2.6.x中请求客户端证书?_Scala_Ssl_Playframework_Ssl Client Authentication - Fatal编程技术网

Scala 为什么不是';我的服务器是否在Play 2.6.x中请求客户端证书?

Scala 为什么不是';我的服务器是否在Play 2.6.x中请求客户端证书?,scala,ssl,playframework,ssl-client-authentication,Scala,Ssl,Playframework,Ssl Client Authentication,我正试图通过以下操作启用客户端身份验证。由于这只是一个实验,我正在生成自签名证书 我有以下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.Confi

我正试图通过以下操作启用客户端身份验证。由于这只是一个实验,我正在生成自签名证书

我有以下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
#!/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
尽管我的服务器需要客户端身份验证,但客户端从未被提示输入证书并成功启动不安全的连接。为什么会发生这种情况?

有一个与此相关的问题

为了实现这一点,sbt
Playakkahtp2Support
需要在试图进行客户端身份验证和规避JDK 161问题的项目中启用