1. 程式人生 > 實用技巧 >為https請求配置ssl(不用keystore,直接用證書,java程式碼)

為https請求配置ssl(不用keystore,直接用證書,java程式碼)

參考連結:

https://stackoverflow.com/questions/12501117/programmatically-obtain-keystore-from-pem

https://stackoverflow.com/questions/6559272/algid-parse-error-not-a-sequence

https://stackoverflow.com/questions/15344125/load-a-rsa-private-key-in-java-algid-parse-error-not-a-sequence/21458628

http://www.bouncycastle.org/latest_releases.html

生成SSLSocketFactory程式碼(核心):

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.xml.bind.DatatypeConverter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths; import java.security.KeyFactory; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; public class KeyTest { public static SSLSocketFactory getSocketFactoryPEM(String certPath, String keyPath) throws Exception { byte[] certByte = Files.readAllBytes(Paths.get(certPath)); byte[] keyByte = Files.readAllBytes(Paths.get(keyPath)); byte[] certBytes = parseDERFromPEM(certByte, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----"); byte[] keyBytes = parseDERFromPEM(keyByte, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----"); X509Certificate cert = generateCertificateFromDER(certBytes); RSAPrivateKey key = generatePrivateKeyFromDER(keyBytes); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(null); keystore.setCertificateEntry("cert-alias", cert); keystore.setKeyEntry("key-alias", key, "<password>".toCharArray(), new Certificate[] {cert}); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(keystore, "<password>".toCharArray()); KeyManager[] km = kmf.getKeyManagers(); SSLContext context = SSLContext.getInstance("TLS"); context.init(km, null, null); return context.getSocketFactory(); } private 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]); } private static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException { java.security.Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider() ); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory factory = KeyFactory.getInstance("RSA"); return (RSAPrivateKey)factory.generatePrivate(spec); } private static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException { CertificateFactory factory = CertificateFactory.getInstance("X.509"); return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes)); } }

後續https請求程式碼:

okhttp:

private void test()throws Exception {
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("test", "123");
    OkHttpClient client = new OkHttpClient.Builder()
      .sslSocketFactory(KeyTest.getSocketFactoryPEM("",""))
      .build();
    Request request = new Request.Builder()
      .url("")
      .post(RequestBody.create(MediaType.parse("application/json"), jsonObject.toJSONString()))
      .build();

    client.newCall(request).enqueue(new Callback() {
      @Override
      public void onFailure(Call call, IOException e) {
        System.out.println("--------------onFailure--------------" + e.toString());
      }

      @Override
      public void onResponse(Call call, Response response) throws IOException {
        System.out.println("--------------onResponse--------------" + response.body().string());
      }
    });
  }