Web支持HTTPS的client(HTTP&XML-RPC)

生成Web自签名的证书(在命令行执行以下命令)

keytool -genkey -keysize 2048 -validity 3650 -keyalg RSA -dname "CN=Hanshow, OU=Hanshow, O=Hanshow, L=Jiaxing, ST=Zhejiang, C=CN" -alias shopweb -keypass password_of_key -storepass password_of_store -keystore shopweb.jks

 

-keysize 2048 指定生成2048位的密钥

-validity 3650 指定证书有效期天数(3650=10年)

-keyalg RSA 指定用RSA算法生成密钥

-dname 设置签发者的信息

-alias 设置别名

-keypass 设定访问key的password

-storepass 设定访问这个KeyStore的password

web.jks指定生成的KeyStore文件名叫web.jks

 

  • 把生成的web.jks存放到classpath路径中。
  • 以下代码依赖Jackson JSON,OkHttp3,Apache XML-RPC Client。
  • 以下的实现全部是基于trustAll,即信任任何服务器

基础SSL工具类SSLUtils

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

public class SSLUtils {
    public static KeyStore loadKeyStore(String type, String fileName, String password) throws Exception {
        try (InputStream input = SSLUtils.class.getClassLoader().getResourceAsStream(fileName)) {
            if (input == null) {
                throw new FileNotFoundException(String.format("cannot find KeyStore file \"%s\" in classpath",
                        fileName));
            }

            KeyStore ks = KeyStore.getInstance(type);
            ks.load(input, password.toCharArray());
            return ks;
        }
    }

    /**
     * 创建SSLSocketFactory
     *
     * @param protocol         SSL协议,默认:TLS
     * @param algorithm        KeyManager算法,默认:SunX509
     * @param provider         KeyManager提供者,默认:SunJSSE
     * @param keyPassword      Key password
     * @param keyStoreType     KeyStore类型,默认:JKS
     * @param keyStoreFileName KeyStore文件名,应在classpath中能找到。
     * @param storePassword    KeyStore的password
     * @return SSLSocketFactory实例
     * @throws Exception
     */
    public static SSLSocketFactory createSSLSocketFactory(String protocol, String algorithm, String provider, String keyPassword,
                                                          String keyStoreType, String keyStoreFileName, String storePassword) throws Exception {

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm, provider);
        KeyStore keyStore = loadKeyStore(keyStoreType, keyStoreFileName, storePassword);
        keyManagerFactory.init(keyStore, keyPassword.toCharArray());

        TrustManager[] trustManagers = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        // Trust always
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        // Trust always
                    }
                }
        };

        SSLContext sslContext = SSLContext.getInstance(protocol);
        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagers,
                new SecureRandom());
        return sslContext.getSocketFactory();
    }

    public static SSLSocketFactory createSSLSocketFactory(String keyPassword, String keyStoreFileName, String storePassword) throws Exception {
        return createSSLSocketFactory("TLS", "SunX509", "SunJSSE", keyPassword,
                "JKS", keyStoreFileName, storePassword);

    }

    public static HostnameVerifier createHostnameVerifier() {
        return (hostname, session) -> true;
    }
}

  XML-RPC Client

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import java.net.URL;

public class DemoXmlRpcClient {
    private static boolean SSLContextInitialized = false;

    private URL url;
    private XmlRpcClient xmlRpcClient;

    public DemoXmlRpcClient(URL url) {
        this.url = url;
        if ("https".equalsIgnoreCase(url.getProtocol())) {
            initSSLContext();
        }

        XmlRpcClientConfigImpl rpcConfig = new XmlRpcClientConfigImpl();
        rpcConfig.setServerURL(this.url);
        // 设置RPC连接超时时间为60秒
        rpcConfig.setConnectionTimeout(60 * 1000);
        // 设置RPC等待响应时间为60秒
        rpcConfig.setReplyTimeout(60 * 1000);
        this.xmlRpcClient = new XmlRpcClient();
        this.xmlRpcClient.setConfig(rpcConfig);
    }

    private synchronized void initSSLContext() {
        if (!SSLContextInitialized) { // 只需要初始化一次
            try {
                SSLSocketFactory sslSocketFactory = SSLUtils.createSSLSocketFactory(
                        "password_of_key", "shopweb.jks", "password_of_store");
                HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
                HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
            } catch (Throwable t) {
                throw new RuntimeException("initialize SSLContext for XML-RPC error", t);
            }
            SSLContextInitialized = true;
        }
    }

    public Object execute(String command, Object[] params) throws Exception {
        return xmlRpcClient.execute(command, params);
    }

    public URL getUrl() {
        return url;
    }

    public static void main(String[] args) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        Object response;

        // 测试通过HTTPS向ESL-Working发送XML-RPC请求
        DemoXmlRpcClient sslClient = new DemoXmlRpcClient(new URL("https://127.0.0.1:9443/RPC2"));
        response = sslClient.execute("send_cmd", new Object[]{"API_VERSION", new Object[]{}});
        System.out.println(objectMapper.writeValueAsString(response));

        // 测试通过HTTP向ESL-Working发送XML-RPC请求
        DemoXmlRpcClient normalClient = new DemoXmlRpcClient(new URL("http://127.0.0.1:9000/RPC2"));
        response = normalClient.execute("send_cmd", new Object[]{"API_VERSION", new Object[]{}});
        System.out.println(objectMapper.writeValueAsString(response));
    }
}

HTTP Client

import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.platform.Platform;

import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeUnit;

public class DemoHttpClient {
    private final static String JSON_MEDIA_TYPE_PATTERN = "application/json; charset=%s";
    private final static String DEFAULT_CHARSET = "utf-8";
    private final static String DEFAULT_CONTENT_TYPE = String.format(JSON_MEDIA_TYPE_PATTERN, DEFAULT_CHARSET);

    private final static ObjectMapper objectMapper = new ObjectMapper();
    private OkHttpClient httpClient;
    private OkHttpClient httpsClient;

    public DemoHttpClient(String keyPassword, String fileName, String storePassword) throws Exception {
        httpClient = new OkHttpClient.Builder()
                .readTimeout(60, TimeUnit.SECONDS)
                .connectTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS).build();

        SSLSocketFactory sslSocketFactory = SSLUtils.createSSLSocketFactory(keyPassword, fileName, storePassword);
        X509TrustManager x509TrustManager = Platform.get().trustManager(sslSocketFactory);
        httpsClient = new OkHttpClient.Builder()
                .readTimeout(60, TimeUnit.SECONDS)
                .connectTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .sslSocketFactory(sslSocketFactory, x509TrustManager)
                .hostnameVerifier(SSLUtils.createHostnameVerifier())
                .build();
    }

    public String get(String url) throws IOException {
        return get(new URL(url));
    }

    public String get(URL url) throws IOException {
        return httpRequest(url, "GET", DEFAULT_CONTENT_TYPE, null);
    }

    public String post(String url, Object data) throws IOException {
        return post(new URL(url), data);
    }

    public String post(URL url, Object object) throws IOException {
        byte[] data = objectMapper.writeValueAsString(object).getBytes(DEFAULT_CHARSET);
        return httpRequest(url, "POST", DEFAULT_CONTENT_TYPE, data);
    }

    public String put(String url, Object data) throws IOException {
        return put(new URL(url), data);
    }

    public String put(URL url, Object object) throws IOException {
        byte[] data = objectMapper.writeValueAsString(object).getBytes(DEFAULT_CHARSET);
        return httpRequest(url, "PUT", DEFAULT_CONTENT_TYPE, data);
    }

    public String httpRequest(URL url, String method, String contentType, byte[] data) throws IOException {
        OkHttpClient client;
        String protocol = url.getProtocol();
        if ("http".equalsIgnoreCase(protocol)) {
            client = httpClient;
        } else if ("https".equalsIgnoreCase(protocol)) {
            client = httpsClient;
        } else {
            throw new UnsupportedOperationException("unsupported protocol: " + protocol);
        }

        Request.Builder builder = new Request.Builder().url(url);
        MediaType mediaType = MediaType.parse(contentType);
        if ("GET".equalsIgnoreCase(method)) {
            builder.get();
        } else {
            RequestBody requestBody = RequestBody.create(mediaType, data == null ? new byte[0] : data);
            builder.method(method, requestBody);
        }

        Request request = builder.build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                ResponseBody responseBody = response.body();
                return responseBody == null ? null : responseBody.string();
            } else {
                throw new IOException(String.format(
                        "%s/%s %s got unexpected response code %d",
                        protocol.toUpperCase(), method, url, response.code()));
            }
        }
    }

    public static void main(String[] args) throws Exception {
        DemoHttpClient httpClient = new DemoHttpClient("password_of_key", "shopweb.jks", "password_of_store");

        // 通过HTTP访问ESL-Working RESTful接口
        System.out.println(httpClient.get("http://127.0.0.1:9000/api2/runinfo"));

        // 通过HTTPS访问ESL-Working RESTful接口
        System.out.println(httpClient.get("https://127.0.0.1:9443/api2/runinfo"));
    }
}

  

 

posted on 2019-08-01 19:35  范兵  阅读(1183)  评论(0编辑  收藏  举报

导航