兩種存取https資源的方式

2020-08-11 20:28:31

1、繞過證書的方式:

     生成httpClient物件類

package com.example.interceptorStu.https;

import org.apache.http.client.HttpClient;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

public class HttpsClientBuilder {

    public static HttpClient getHttpsClient() throws KeyManagementException, NoSuchAlgorithmException {
        //採用繞過驗證的方式處理https請求
        SSLContext sslcontext = createIgnoreVerifySSL();

        //設定協定http和https對應的處理socket鏈接工廠的物件
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", new SSLConnectionSocketFactory(sslcontext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER))
                .build();
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        HttpClients.custom().setConnectionManager(connManager);

        //建立自定義的httpclient物件
        CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();
        return client;
    }

    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("TLS");

        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sc.init(null, new TrustManager[] { trustManager }, null);
        return sc;
    }
}

 請求工具類:

package com.example.interceptorStu.https;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * http請求工具類
 */
@Slf4j
public class HttpClientUtil {

    /**
     * get 方式請求
     * @param url
     * @return
     */
    public static String get(String url, CloseableHttpClient client){

        String result = null;
        try {
            //發送get請求
            HttpGet httpGet = new HttpGet(url);
            log.info("get方式http請求, url : {}", url);
            HttpResponse response = client.execute(httpGet);
            /**請求發送成功,並得到響應**/
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                /**讀取伺服器返回過來的json字串數據**/
                result = EntityUtils.toString(response.getEntity(), "utf-8");
                log.info("get方式http請求, 返回結果:{}", result);
            }else{
                log.error("get方式http請求失敗, 狀態碼:{}", statusCode);
            }
        } catch (Exception e) {
            log.error("get方式http請求異常: ", e);
        }
        finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return result;
        }
    }

    /**
     * post請求  contentType=x-www-form-urlencoded
     * @param url
     * @param bodyParam
     * @return
     */
    public static String post(String url, Map<String, String> bodyParam, Map<String, String> headerParam, CloseableHttpClient client){

        String result = null;
        try {
            //body參數
            List<BasicNameValuePair> param = new ArrayList<BasicNameValuePair>();
            if(bodyParam != null && bodyParam.size() > 0){
                bodyParam.keySet().forEach(key ->{
                    param.add(new BasicNameValuePair(key, bodyParam.get(key)));
                });
            }
            //header參數
            Header[] headers = null;
            if(headerParam != null && headerParam.size() > 0){
                headers = new Header[headerParam.size()];
                int i = 0;
                for(String key : headerParam.keySet()){
                    BasicHeader basicHeader = new BasicHeader(key, headerParam.get(key));
                    headers[i] = basicHeader;
                    i++;
                }
            }
            HttpEntity entity = new UrlEncodedFormEntity(param, "utf-8");
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(entity);
            httpPost.setHeaders(headers);
            log.info("post方式http請求, url : {}, bodyParam: {}, headerParam: {}", url, JSON.toJSONString(bodyParam), JSON.toJSONString(headerParam));
            HttpResponse response = client.execute(httpPost);
            /**請求發送成功,並得到響應**/
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                /**讀取伺服器返回過來的json字串數據**/
                result = EntityUtils.toString(response.getEntity(), "utf-8");
                log.info("post方式http請求, 返回結果:{}", result);
            } else {
                log.error("post方式http請求失敗, 狀態碼:{}", statusCode);
            }
        } catch (Exception e) {
            log.error("post方式http請求異常: ", e);
        }
        finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return result;
        }
    }

    /**
     * postJson請求  contentType=application/json
     * @param url
     * @param jsonBodyParam
     * @param headerParam
     * @return
     */
    public static String postJson(String url, String jsonBodyParam, Map<String, String> headerParam,CloseableHttpClient client){

        String result = null;
        try {
            //header參數
            Header[] headers = null;
            if(headerParam != null && headerParam.size() > 0){
                headers = new Header[headerParam.size()];
                int i = 0;
                for(String key : headerParam.keySet()){
                    BasicHeader basicHeader = new BasicHeader(key, headerParam.get(key));
                    headers[i] = basicHeader;
                    i++;
                }
            }
            StringEntity entity = new StringEntity(jsonBodyParam, ContentType.APPLICATION_JSON);
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(entity);
            httpPost.setHeaders(headers);
            log.info("postJson方式http請求, url : {}, jsonBodyParam: {}, headerParam: {}", url, jsonBodyParam, JSON.toJSONString(headerParam));
            HttpResponse response = client.execute(httpPost);
            /**請求發送成功,並得到響應**/
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                /**讀取伺服器返回過來的json字串數據**/
                result = EntityUtils.toString(response.getEntity(), "utf-8");
                log.info("postJson方式http請求, 返回結果:{}", result);
            } else {
                log.error("postJson方式http請求失敗, 狀態碼:{}", statusCode);
            }
        } catch (Exception e) {
            log.error("postJson方式http請求異常: ", e);
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return result;
        }
    }
}

 測試類:

package com.example.interceptorStu.https;

import org.apache.http.impl.client.CloseableHttpClient;

import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        try {
            CloseableHttpClient client = (CloseableHttpClient) HttpsClientBuilder.getHttpsClient();
            String jsonBodyParam = "{\"x\":2,\"y\":3}";
            Map<String, String> headerParam = new HashMap<>();
            headerParam.put("a","1");
            headerParam.put("b","2");
            String result = HttpClientUtil.postJson("https://localhost:22225/api/getUser2",jsonBodyParam,headerParam,client);
            System.out.println("-----result---------"+result);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

2、帶證書的請求:

package com.example.interceptorStu;

import okhttp3.*;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

/**
 * https單向認證
 */
public class HttpsTest {

    //安全傳輸層協定
    private static final String PROTOCOL = "TLS";

    // JKS/PKCS12
    private static final String KEY_KEYSTORE_TYPE = "PKCS12";

    private static SSLSocketFactory getSocketFactory(String cerPath) throws Exception {
        SSLSocketFactory socketFactory = null;
        try (InputStream cerInputStream = new FileInputStream(new File(cerPath))) {
            TrustManager[] trustManagers = getTrustManagers(cerInputStream);
            SSLContext sslContext = getSslContext(trustManagers);
            socketFactory = sslContext.getSocketFactory();
        }
        return socketFactory;
    }

    private static SSLContext getSslContext(TrustManager[] trustManagers) throws Exception {
        SSLContext sslContext = SSLContext.getInstance(PROTOCOL);
        sslContext.init(null, trustManagers, new SecureRandom());
        return sslContext;
    }

    private static TrustManager[] getTrustManagers(InputStream inputStream) throws Exception {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        KeyStore keyStore = KeyStore.getInstance(KEY_KEYSTORE_TYPE);
        //載入證書
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Certificate ca = certificateFactory.generateCertificate(inputStream);
        keyStore.load(null, null);
        //設定公鑰
        keyStore.setCertificateEntry("server", ca);
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        return trustManagers;
    }

    public static void main(String[] args) throws Exception {
        //獲取SSLSocketFactory
        String certPath = "C:\\key\\huiju.cer";//伺服器端公鑰
        SSLSocketFactory socketFactory = getSocketFactory(certPath);
        //發送請求
        String url = "https://localhost:8443/say/Myhello";
    //    String url = "https://localhost:8443/say/hello";     get
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        clientBuilder.sslSocketFactory(socketFactory);
        //解決報錯javax.net.ssl.SSLPeerUnverifiedException: Hostname 127.0.0.1 not verified
        clientBuilder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                System.out.println("主機:" + s);
                return true;
            }
        });
        OkHttpClient client = clientBuilder.build();

//get        Request.Builder builder = new Request.Builder().url(url);
// get       Request request = builder.build();

        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSON, "");
        Request request = new Request.Builder().url(url).post(body).build();

        Response response = client.newCall(request).execute();
        String result = response.body().string();
        //列印請求結果
        System.out.println(result);
    }

}