Я использую Akka (версия 2.5.18) для отправки строк JSON на определенный сервер через https.Я использовал poolRouter (балансировочный пул с 10 экземплярами) для создания пула актеров, которые собираются отправлять JSON (сгенерированные от разных клиентов) на один сервер:
val router: ActorRef = system.actorOf(
FromConfig.props(Props(new SenderActor(configuration.getString("https://server.com"), this.self))),
"poolRouter"
)
В спецификации проекта сказано, что запросы также могут быть отправлены с помощью curl:
curl -X PUT --cert certificate.pem --key private.key -H 'Content-Type: application / json' -H 'cache-control: no-cache' -d '[{"id" : "test"}] 'https://server.com'
Где "certificate.pem" - это сертификат tls клиента, а "private.key" - используемый закрытый ключ.для создания CSR клиента.
Я использую балансировочный пул, потому что у меня будет очень большой набор сертификатов (по одному для каждого клиента), и мне нужно отправлять запросы одновременно.
Мой подход заключается в том, чтобы иметь класс "SenderActor", который будет создан балансирующим пулом.Каждый участник после получения сообщения с «customerId» и данными JSON, сгенерированными этим клиентом, отправит запрос https:
override def receive: Receive = {
case Data(customerId, jsonData) =>
send(customerId(cid, jsonData))
Каждый SenderActor прочитает сертификат (и закрытый ключ)на основе пути с использованием customerId.Например, customerId: «cust1» будет хранить свой сертификат и ключ в «/ home / test / cust1».Таким образом, один и тот же класс акторов может использоваться для всех клиентов.
В соответствии с документацией , мне нужно создать HttpsConnectionContext
для отправки различных запросов:
def send(customerId: String, dataToSend): Future[HttpResponse] = {
// Create the request
val req = HttpRequest(
PUT,
uri = "https://server.com",
entity = HttpEntity(`application/x-www-form-urlencoded` withCharset `UTF-8`, dataToSend),
protocol = `HTTP/1.0`)
val ctx: SSLContext = SSLContext.getInstance("TLS")
val permissiveTrustManager: TrustManager = new X509TrustManager() {
override def checkClientTrusted(chain: Array[X509Certificate], authType: String): Unit = {}
override def checkServerTrusted(chain: Array[X509Certificate], authType: String): Unit = {}
override def getAcceptedIssuers(): Array[X509Certificate] = Array.empty
}
ctx.init(Array.empty, Array(permissiveTrustManager), new SecureRandom())
val httpsConnContext: HttpsConnectionContext = ConnectionContext.https(ctx)
// Send the request
Http(system).singleRequest(req, httpsConnContext)
}
Проблема, с которой я столкнулся, заключается в том, что я не имею ни малейшего понятия о том, как «установить сертификат и ключ» в запросе, чтобы сервер их принимал.
Например,Я могу прочитать сертификат, используя следующий код:
import java.util.Base64
val certificate: String => String = (customer: String) => IO {
Source.fromInputStream(getClass.getClassLoader
.getResourceAsStream("/home/test/".concat(customer).concat("_cert.pem")))
.getLines().mkString
}.unsafeRunSync()
val decodedCertificate = Base64.getDecoder.decode(certificate(customerId)
.replaceAll(X509Factory.BEGIN_CERT, "").replaceAll(X509Factory.END_CERT, ""))
val cert: Certificate = CertificateFactory.getInstance("X.509")
.generateCertificate(new ByteArrayInputStream(decodedCertificate))
Но я не знаю, как «установить» этот сертификат и закрытый ключ в запросе (который защищен парольной фразой), поэтомучто сервер это принимает.
Любая подсказка или помощь будет принята с благодарностью.