如何向https webapi发出发布请求?

时间:2019-09-20 09:35:21

标签: java ssl https

我正在编写一个程序,该程序需要使用https Post将数据发送到webapi。我提供了一个.pem文件,提供商说我将需要该文件才能连接到api。现在,我被困在对此证书文件提出正确的发布请求。有人可以帮忙吗?

下面是到目前为止我得到的,它确实可以运行,但是遇到了

  

java.security.cert.CertificateException:在sun.security.util.HostnameChecker.matchIP上不存在使用者替代名称

我已经搜索了此异常。有人说我应该在代码中使用域名而不是IP地址。但是,我提供的api仅以IP形式提供。我还要检查.pem文件中的CN。它也是ip形式而不是域形式。

    public void httpPost(String json) throws Exception {
    System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2,SSLv3");
    InputStream stream = getClass().getClassLoader().getResourceAsStream("test.pem");
    File targetFile = new File("test_cert.pem");
    try {
        FileUtils.copyInputStreamToFile(stream, targetFile);
    } 
    catch (IOException e) {
        e.printStackTrace();
    }
    try {
        //String key;
        System.out.println("SSL");
        SSLSocketFactory sf = getSocketFactoryPEM(targetFile);
        URL url = new URL("https://xxxxxxx");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("Content-Length", String.valueOf(json.getBytes().length));
        conn.setSSLSocketFactory(sf);
        conn.getOutputStream().write(json.getBytes());
        conn.getOutputStream().flush();
        conn.getInputStream().close();
        System.out.println("Send message.");
        BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));

        String output;
        System.out.println("Output from Server .... \n");
        while ((output = br.readLine()) != null) {
            System.out.println(output);
        }

        conn.disconnect();
        System.out.println("Got response.");

    } catch (MalformedURLException e) {

        e.printStackTrace();

    } catch (IOException e) {

        e.printStackTrace();

    }

}

protected static SSLSocketFactory getSocketFactoryPEM(File file) throws Exception {
    byte[] certAndKey = FileUtils.readFileToByteArray(file);

    byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");

    X509Certificate cert = generateCertificateFromDER(certBytes);                

    KeyStore keystore = KeyStore.getInstance("JKS");
    keystore.load(null);
    keystore.setCertificateEntry("cert-alias", cert);

    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    kmf.init(keystore, "123456".toCharArray());

    KeyManager[] km = kmf.getKeyManagers(); 

    SSLContext context = SSLContext.getInstance("TLS");
    context.init(km, null, null);

    return context.getSocketFactory();
}

protected static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
    String data = new String(pem);
    String[] tokens = data.split(beginDelimiter);
    tokens = tokens[1].split(endDelimiter);
    return DatatypeConverter.parseBase64Binary(tokens[0]);        
}

protected static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
    CertificateFactory factory = CertificateFactory.getInstance("X.509");

    return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes));      
}

0 个答案:

没有答案