使用 JAX WS 的 POJO https 客户端的简单配置

问题描述 投票:0回答:1

我正在尝试获得一个与 JAX-WS 一起运行的简单 POJO https 客户端/服务器实现。

服务器端似乎运行良好并且相当简单,但我还没有找到如何以简单的方式配置客户端。

我已经让它与几个属性一起使用以包含服务器密钥库。
但是,当然,这仅适用于测试。

有什么想法吗?

我将 JDK 17 与 Eclipse 2023-09 结合使用。

有关密钥库和证书的详细信息,请参阅源代码中的注释。

为了方便起见,我已将它们发布到paste.c-net.org:
密钥库 keystore.password.p12
证书keystore.password.cer

来源如下:

package uk.co.sslws6001.server;

import java.io.FileInputStream;
import java.net.InetSocketAddress;
import java.net.URL;
import java.security.KeyStore;
import java.util.HexFormat;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.xml.namespace.QName;

import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;

import jakarta.jws.WebParam;
import jakarta.jws.WebService;
import jakarta.xml.ws.Endpoint;
import jakarta.xml.ws.Service;

public class WS {
    @WebService
    public interface MyWebService {
        public String             toHexDigits(@WebParam(name="intValue") final int intValue);
    }
    @WebService(endpointInterface=                       "uk.co.sslws6001.server.WS$MyWebService")
    public static final class MyWebServiceImpl implements uk.co.sslws6001.server.WS.MyWebService {
        @Override
        public String             toHexDigits(final int intValue) {
            return HexFormat.of().toHexDigits(          intValue);
        }
    }

    /*
     * Keystore & Certificate created thus:
     * keytool.exe  -genkeypair  -alias self_signed  -keystore keystore.password.p12  -storepass password  -keypass password  -keyalg RSA  -validity 99999  -storetype PKCS12
     * keytool.exe  -export      -alias self_signed  -keystore keystore.password.p12  -storepass password  -file keystore.password.cer
     */
    private static HttpsServer createHttpsServer() throws Exception {

        final     var pw  =                      "password".toCharArray();
        final     var ks  = KeyStore.getInstance("pkcs12");

        try(final var fis = new FileInputStream ("keystore.password.p12")) {
            ;         ks.load(fis, pw);
        }
        final     var kmf = KeyManagerFactory  .getInstance("SunX509");
        ;             kmf.init(ks, pw);

        final     var tmf = TrustManagerFactory.getInstance("SunX509");
        ;             tmf.init(ks);

        final     var sslContext = SSLContext.getInstance("TLS");
        ;             sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        final     var httpsServer =  HttpsServer.create(new InetSocketAddress("localhost", 6001), 0);
        ;             httpsServer.setHttpsConfigurator (new HttpsConfigurator(sslContext));

        return        httpsServer;
    }

    public  static void main(final String[] args) throws Exception {

        final var httpsAddress  = "/uk/co/sslws6001/server/MyWebService";
        final var implementor   = new MyWebServiceImpl();

        System.out.println("publishing.........: " + httpsAddress + "\t-> " + implementor);

        final var httpsServer   = createHttpsServer();

        final var httpsContext  = httpsServer.createContext(httpsAddress);
        final var httpsEndpoint = Endpoint.create(implementor);
        ;         httpsEndpoint.publish(httpsContext);
        try {
            httpsServer.start();

            System.out.println("https Server up....: " + httpsServer);

            testClient();
        }
        finally {
            httpsServer.stop(3);
            System.out.println("https Server DOWN...");
        }
    }

    private static void testClient() throws Exception {
        System.out.println("Test Client.........");

        /*
         * TODO get https Client to work WITHOUT following 2 lines (Servers private!! Keystore)...
         * ...: i.e. use the Servers exported Certificate ("keystore.password.cer") instead.
         */
        System.getProperties().put("javax.net.ssl.trustStore",         "keystore.password.p12");  
        System.getProperties().put("javax.net.ssl.trustStorePassword", "password");

        final var serviceQName   = new QName("http://server.sslws6001.co.uk/", "MyWebServiceImplService");

        final var serviceWsdlURL = new URL  ("https://localhost:6001/uk/co/sslws6001/server/MyWebService?wsdl");

        final var service        = Service.create(serviceWsdlURL, serviceQName);
        final var serviceProxy   = service.getPort(uk.co.sslws6001.server.WS.MyWebService.class);

        System.out.println("Service............: " + service);
        System.out.println("Service Proxy......: " + serviceProxy);

        System.out.println("Result Hex Digits..: " + serviceProxy.toHexDigits((int) System.currentTimeMillis()));
    }
}

这是 POM:

<project
        xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>uk.co.sslws6001</groupId>
    <artifactId>client.server</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-ri</artifactId>
            <version>4.0.1</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>
java jax-ws
1个回答
0
投票

好的,解决方案是...

HttpsURLConnection.setDefaultSSLSocketFactory(getCustomSSLSocketFactory());

getCustomSSLSocketFactory()
也不是太啰嗦。

这是一个工作示例:

package uk.co.sslws6001.server;

import java.io.FileInputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URL;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.HexFormat;
import java.util.LinkedList;
import java.util.Optional;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.xml.namespace.QName;

import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;

import jakarta.jws.WebParam;
import jakarta.jws.WebService;
import jakarta.xml.ws.Endpoint;
import jakarta.xml.ws.Service;

public class WS {
    @WebService
    public interface MyWebService {
        public String             toHexDigits(@WebParam(name="intValue") final int intValue);
    }
    @WebService(endpointInterface=                       "uk.co.sslws6001.server.WS$MyWebService")
    public static final class MyWebServiceImpl implements uk.co.sslws6001.server.WS.MyWebService {
        @Override
        public String             toHexDigits(final int intValue) {
            return HexFormat.of().toHexDigits(          intValue);
        }
    }

    /*
     * Keystore & Certificate created thus:
     * keytool.exe  -genkeypair  -alias self_signed  -keystore keystore.password.p12  -storepass password  -keypass password  -keyalg RSA  -validity 99999  -storetype PKCS12
     * keytool.exe  -export      -alias self_signed  -keystore keystore.password.p12  -storepass password  -file keystore.password.cer
     */
    private static HttpsServer createHttpsServer() throws Exception {

        final     var pw  =                      "password".toCharArray();
        final     var ks  = KeyStore.getInstance("pkcs12");

        try(final var fis = new FileInputStream ("keystore.password.p12")) {
            ;         ks.load(fis, pw);
        }
        final     var kmf = KeyManagerFactory  .getInstance("SunX509");
        ;             kmf.init(ks, pw);

        final     var tmf = TrustManagerFactory.getInstance("SunX509");
        ;             tmf.init(ks);

        final     var sslContext = SSLContext.getInstance("TLS");
        ;             sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        final     var httpsServer =  HttpsServer.create(new InetSocketAddress("localhost", 6001), 0);
        ;             httpsServer.setHttpsConfigurator (new HttpsConfigurator(sslContext));

        return        httpsServer;
    }

    public  static void main(final String[] args) throws Exception {

        final var httpsAddress  = "/uk/co/sslws6001/server/MyWebService";
        final var implementor   = new MyWebServiceImpl();

        System.out.println("publishing.........: " + httpsAddress + "\t-> " + implementor);

        final var httpsServer   = createHttpsServer();

        final var httpsContext  = httpsServer.createContext(httpsAddress);
        final var httpsEndpoint = Endpoint.create(implementor);
        ;         httpsEndpoint.publish(httpsContext);
        try {
            httpsServer.start();

            System.out.println("https Server up....: " + httpsServer);

            testClient();
        }
        finally {
            httpsServer.stop(3);
            System.out.println("https Server DOWN...");
        }
    }

    private static void testClient() throws Exception {
        System.out.println("Test Client.........");

        HttpsURLConnection.setDefaultSSLSocketFactory(getCustomSSLSocketFactory());

        final var serviceQName   = new QName("http://server.sslws6001.co.uk/", "MyWebServiceImplService");

        final var serviceWsdlURL = new URL  ("https://localhost:6001/uk/co/sslws6001/server/MyWebService?wsdl");

        final var service        = Service.create(serviceWsdlURL, serviceQName);
        final var serviceProxy   = service.getPort(uk.co.sslws6001.server.WS.MyWebService.class);

        System.out.println("Service............: " + service);
        System.out.println("Service Proxy......: " + serviceProxy);

        System.out.println("Result Hex Digits..: " + serviceProxy.toHexDigits((int) System.currentTimeMillis()));
    }

    private static SSLSocketFactory getCustomSSLSocketFactory() throws Exception {

        final var sslContext    = SSLContext.getInstance("TLS");
        ;         sslContext.init(null, new TrustManager[] {getCustomTrustManager()}, new SecureRandom());

        final var socketFactory = sslContext.getSocketFactory();

        System.out.println("Custom SockFactory.: " + socketFactory);

        return    socketFactory;
    }

    private static X509ExtendedTrustManager getCustomTrustManager() {

        final var okCerts = new LinkedList<X509Certificate>();

        getServerPublicCertificate().ifPresent(okCerts :: add);

        return new X509ExtendedTrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[0];
            }
            @Override
            public void checkClientTrusted(final X509Certificate[] chain, final String authType)                         throws CertificateException {
                throw new UnsupportedOperationException();
            }
            @Override
            public void checkServerTrusted(final X509Certificate[] chain, final String authType)                         throws CertificateException {
                throw new UnsupportedOperationException();
            }
            @Override
            public void checkClientTrusted(final X509Certificate[] chain, final String authType, final Socket socket)    throws CertificateException {
                throw new UnsupportedOperationException();
            }
            @Override
            public void checkServerTrusted(final X509Certificate[] chain, final String authType, final Socket socket)    throws CertificateException {
                System.out.println("checkServerTrusted.: chain=" + chain + " authType=" + authType + " socket=" + socket);

                for (    final var suppliedCert : chain) {
                    for (final var okCert       : okCerts) {

                        if (suppliedCert.equals(okCert)) {
                            System.out.println("Certificate ok.....: id=" + suppliedCert.getSerialNumber());
                            return;
                        } else {
                            System.out.println("Certificate BAD....: id=" + suppliedCert.getSerialNumber());
                        }
                    }
                }
                throw new CertificateException("Bad Karma!");
            }
            @Override
            public void checkClientTrusted(final X509Certificate[] chain, final String authType, final SSLEngine engine) throws CertificateException {
                throw new UnsupportedOperationException();
            }
            @Override
            public void checkServerTrusted(final X509Certificate[] chain, final String authType, final SSLEngine engine) throws CertificateException {
                throw new UnsupportedOperationException();
            }
        };
    }

    private static Optional<X509Certificate> getServerPublicCertificate() {

        try(final var is   = new FileInputStream("keystore.password.cer")) {

            final var fac  = CertificateFactory.getInstance("X509");
            final var cert = (X509Certificate) fac.generateCertificate(is);

            System.out.print  ("Server Public Cert.: sn=" + cert.getSerialNumber());
            System.out.println(      " -> Validity.: " + cert.getNotBefore() + " to " + cert.getNotAfter());

            final var now = new Date();

            if (now.before(cert.getNotBefore())
            ||  now.after (cert.getNotAfter())) {
                System.out.println("Certificate INVALID: sn=" + cert.getSerialNumber());
                return Optional.empty();
            }
            return     Optional.of(cert);
        }
        catch (final Exception e) {
            return     Optional.empty();
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.