JAX-WS CXF WSS4J Добавление сертификатов во время выполнения для подписи сообщений

Мне нужен клиент JAX-WS (созданный с помощью wsdl2java), чтобы подписывать его сообщения и проверять подпись ответных сообщений. Это должно быть не на транспортном уровне, а на уровне сообщений. Сертификат неизвестен во время компиляции (каждый пользователь имеет свой собственный сертификат и загружается).

Если бы это было на транспортном уровне, я бы создал хранилище ключей с необходимым сертификатом и из него создал KeyManagerFactory. - Trustfactory будет создан таким же образом, но повторно использован.

    val certFactory = CertificateFactory.getInstance("X.509")

    val certStream = getResource("file").openStream().buffered()
    val cert = certFactory.generateCertificate(certStream)

    val clientKeystore = KeyStore.getInstance(KeyStore.getDefaultType())
    clientKeystore.load(null, null)
    clientKeystore.setCertificateEntry("certificate", cert)

    val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
    kmf.init(clientKeystore, "".toCharArray())

    val caCertStream = getResource("file").openStream().buffered()
    val caCert = certFactory.generateCertificate(caCertStream)

    val caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType())
    caKeyStore.load(null, null)
    caKeyStore.setCertificateEntry("ca-certificate", caCert)

    val context = SSLContext.getInstance("TLSv1.2")
    context.init(keyManagerFactory.keyManagers, trustManagerFactory.trustManagers, null)
    requestContext.put(JAXWSProperties.SSL_SOCKET_FACTORY, context.socketFactory)

Однако, поскольку это должно быть на уровне сообщения, мне нужно использовать WSS4J, и, насколько я могу судить, это работает только с файлом свойств, который ссылается на файл хранилища ключей.

Как я могу добавить сертификаты для подписи и проверки на уровне сообщений с помощью WSS4J?


person Jarl    schedule 16.04.2020    source источник


Ответы (1)


Я забыл опубликовать свой ответ; лучше поздно, чем никогда.

Хитрость заключается в переопределении метода loadCryptoFromPropertiesFile в WSS4JOutInterceptor и WSS4JInInterceptor. Вместо того, чтобы загружать его из файла, вы просто загружаете его из того, что вы создали в режиме реального времени.

        val cryptoProvider = Merlin()
        cryptoProvider.setTrustStore(trustKeyStore)
        cryptoProvider.setKeyStore(keystore)

        val fetchClient = ClientProxy.getClient(fetchPort)
        val fetchEndpoint = fetchClient.endpoint

        val wssOut: WSS4JOutInterceptor = object : WSS4JOutInterceptor(outProps) {
            override fun loadCryptoFromPropertiesFile(propFilename: String, reqData: RequestData): Crypto {
                return cryptoProvider
            }
        }
        fetchEndpoint.outInterceptors.add(wssOut)

        val wssIn: WSS4JInInterceptor = object : WSS4JInInterceptor(inProps) {
            override fun loadCryptoFromPropertiesFile(propFilename: String, reqData: RequestData): Crypto {
                return cryptoProvider
            }
        }
        fetchEndpoint.inInterceptors.add(wssIn)

person Jarl    schedule 26.11.2020