httpClient请求https-ssl验证的几种方法

2023-01-06  本文已影响0人  haiyong6

要对接外部系统,对方提供了一个p12(PFX)证书,提供一个解密这个证书的密码。

方法一:httpClient支持直接用p12证书和密码的方式请求ssl(PKCS12)

httpClient支持直接用p12证书和密码的方式请求ssl,示例如下:

public static String post(JSONObject json, String url, Map<String, String> headerMap,String p12Path, String password) throws Exception{
        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLContext sslContext = getSSlContext(p12Path, password);
        builder.setSSLContext(sslContext);
        CloseableHttpClient httpclient = builder.build();
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse  response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(json.toString(),"utf-8");
//            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type","application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry:headerEntries){
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber= new StringBuilder();
            String line = null;
            while((line = br.readLine())!=null){
                strber.append(line+'\n');
            }
            result = strber.toString();
            if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){
                if(StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if(null != br) br.close();
            if(null != in) in.close();
            if(null != response) response.close();
            if(null != httpclient) httpclient.close();
        }
        return result;
    }

private static SSLContext getSSlContext(String p12Path, String password) {
        SSLContext  sslContext = null;
        try {
            KeyStore kstore = KeyStore.getInstance("PKCS12");
            kstore.load(new FileInputStream(p12Path), password.toCharArray());
            KeyManagerFactory keyFactory = KeyManagerFactory.getInstance("sunx509");
            keyFactory.init(kstore, password.toCharArray());
            
            sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(keyFactory.getKeyManagers(), null, (SecureRandom) null);
        } catch (Exception e) {
            e.printStackTrace();

        }
        return sslContext;
    }

这种方法输入的是p12文件地址,一般不会直接这样用,用文件的形式管理证书秘钥不太安全,一般是会转成crt证书之后,存到vault里。

方法二:httpClient也支持用crt证书和privateKey的请求(JKS)

先把p12(PFX)证书转成PEM

openssl pkcs12 -in  xxx.pfx -nodes -out server.pem

pem继续提取私钥:

openssl rsa -in server.pem -out server.key

pem提取验证证书:

openssl x509 -in server.pem -out server.crt

如此我们就得到了一个X509协议的crt证书

-----BEGIN CERTIFICATE-----
xxxxx
-----END CERTIFICATE-----

和一个pkcs1的私钥key

-----BEGIN RSA PRIVATE KEY-----
xxxxx
-----END RSA PRIVATE KEY-----

如此就可以用下面代码来实现:

public static String post(String json, String url, Map<String, String> headerMap,String crt, String privateKey) throws Exception{
        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLConnectionSocketFactory sslf = getSSlContextByCrtAndKey(crt, privateKey);
//      builder.setSSLContext(sslContext);
        builder.setSSLSocketFactory(sslf);
        CloseableHttpClient httpclient = builder.build();
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse  response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(json,"utf-8");
//            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type","application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry:headerEntries){
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber= new StringBuilder();
            String line = null;
            while((line = br.readLine())!=null){
                strber.append(line+'\n');
            }
            result = strber.toString();
            if(response.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){
                if(StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if(null != br) br.close();
            if(null != in) in.close();
            if(null != response) response.close();
            if(null != httpclient) httpclient.close();
        }
        return result;
    }

private static SSLConnectionSocketFactory getSSlContextByCrtAndKey(String crt, String privateKey) {
        SSLConnectionSocketFactory sslsf = null;
        try {
            String crtContent = crt.split("-----BEGIN CERTIFICATE-----\n")[1].split("\n-----END CERTIFICATE-----")[0];
            CertificateFactory factory = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(crtContent)));
            
            RSAPrivateKey key = (RSAPrivateKey)parseKey(privateKey, null);

            KeyStore keystore = KeyStore.getInstance("JKS");
            keystore.load(null);
            keystore.setCertificateEntry("cert-alias", cert);
             //生成证书的密码,修改为自己的
            keystore.setKeyEntry("key-alias", key, "123456".toCharArray(),new Certificate[] {cert});
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(keystore, "123456".toCharArray());

           //根据你的jdk版本决定是TLS、TLSv1.1、TLSv1.2
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            context.init(kmf.getKeyManagers(), null, null);
            sslsf = new  SSLConnectionSocketFactory(context);
        } catch (Exception e) {
            e.printStackTrace();

        }
        return sslsf;
    }

这个私钥是pkcs1的,java里一般使用pkcs8的,pkcs8一般是这样的形式:

-----BEGIN PRIVATE KEY-----
xxxxx
-----END PRIVATE KEY-----

pkcs1转pkcs8可以用下面的代码来转换(先去掉一头一尾比如:-----BEGIN RSA PRIVATE KEY----- 、-----END RSA PRIVATE KEY-----、 -----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----,只拿中间的部分):

//format PKCS#1 to PKCS#8
    public static String formatPkcs1ToPkcs8(String privateKey) throws Exception {
        String result = null;
        if (StringUtils.isNotBlank(privateKey))
        {
            //将BASE64编码的私钥字符串进行解码
            byte[] encodeByte = Base64.decodeBase64(privateKey);
            
            AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag);    //PKCSObjectIdentifiers.pkcs8ShroudedKeyBag        
//            ASN1Object asn1Object = ASN1Object.fromByteArray(encodeByte);
            ASN1Object asn1Object = ASN1ObjectIdentifier.fromByteArray(encodeByte);
            PrivateKeyInfo privKeyInfo = new PrivateKeyInfo(algorithmIdentifier, asn1Object);            
            byte[] pkcs8Bytes = privKeyInfo.getEncoded();
            
//            String type = "PRIVATE KEY";
//            result = format2PemString(type, pkcs8Bytes); // 格式化为pem多行格式输出
            return Base64.encodeBase64String(pkcs8Bytes); // 直接一行字符串输出
            
        }
        return result;
    }

上面的post方法中并没有用这个方法去转换pkcs8,而是用的下面的pasekey方法转的,这个方法可以直接传入pem形式的私钥。

/**
     * Parses a Key instance from a PEM representation.
     * <p>
     * When the provided key is encrypted, the provided pass phrase is applied.
     *
     * @param pemString  a PEM representation of a private key (cannot be null or empty)
     * @param passPhrase optional pass phrase (must be present if the private key is encrypted).
     * @return a  Key instance (never null)
     */
    public static Key parseKey(String pemString, String passPhrase) throws IOException {

        if (passPhrase == null) {
            passPhrase = "";
        }
        try (StringReader reader = new StringReader(pemString); //
             PEMParser pemParser = new PEMParser(reader)) {

            final Object object = pemParser.readObject();
            final JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);

            final KeyPair kp;

            if (object instanceof PEMEncryptedKeyPair) {
                // Encrypted key - we will use provided password
                final PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(passPhrase.toCharArray());
                kp = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
            } else if (object instanceof PKCS8EncryptedPrivateKeyInfo) {
                // Encrypted key - we will use provided password
                try {
                    final PKCS8EncryptedPrivateKeyInfo encryptedInfo = (PKCS8EncryptedPrivateKeyInfo) object;
                    final InputDecryptorProvider provider = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passPhrase.toCharArray());
                    final PrivateKeyInfo privateKeyInfo = encryptedInfo.decryptPrivateKeyInfo(provider);
                    return converter.getPrivateKey(privateKeyInfo);
                } catch (PKCSException | OperatorCreationException e) {
                    throw new IOException("Unable to decrypt private key.", e);
                }
            } else if (object instanceof PrivateKeyInfo) {
                return converter.getPrivateKey((PrivateKeyInfo) object);
            } else if (object instanceof SubjectPublicKeyInfo) {
                return converter.getPublicKey((SubjectPublicKeyInfo) object);
            } else {
                // Unencrypted key - no password needed
                kp = converter.getKeyPair((PEMKeyPair) object);
            }
            return kp.getPrivate();
        }
    }

用这个方法前要初始化下面这个:

static {
        java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

====2022-12-19补充更新====
也可以直接设置信任所有证书的方式请求通ssl

信任所有的站点

      HttpClientBuilder builder = HttpClientBuilder.create();
      SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                return true;
            }
        }).build();
        SSLConnectionSocketFactory sslf = new SSLConnectionSocketFactory(sslContext,
                NoopHostnameVerifier.INSTANCE);
        builder.setSSLSocketFactory(sslf);
        CloseableHttpClient httpclient = builder.build();

下面记录一个application/octet-stream发送文件请求例子:

package com.ly.mp.ota.apimanage.controller;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import com.ly.mp.ota.apimanage.utils.HttpRequestUtil;

import ly.mp.project.common.util.HmacSHA256Util;

public class Test {
    public static void main(String[] args) throws Exception {
        String appId = "eb22c0efa9da472db59430c7d0b8cqwe";
        String appSecret = "db70c735ded44902a5d3fc29822dert";
        
        String contentType = "application/octet-stream";
        String url = "https://xxx/putfile";
        String filePath = "D://upload/TEST0408S003.tar.gz";
        File file = new File(filePath);
        
        String date = String.valueOf(System.currentTimeMillis());
        String encoding = "UTF-8";
        String length = String.valueOf(file.length());
        String md5Hash = "";
        String stringToSign = encoding + "\n" + length + "\n" + md5Hash + "\n" + contentType + "\n" + date + "\n" + appId;
        String hmacSHA = HmacSHA256Util.hmacSHA256(appSecret, stringToSign);
        
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", appId + ":" + hmacSHA);
        headerMap.put("x-version", "2022-06-27");
//      headerMap.put("Content-Length", length);
        headerMap.put("Content-Type", contentType);
        headerMap.put("Content-Encoding", encoding);
        headerMap.put("Date", date);
        headerMap.put("x-content-disposition", "attachment; filename=\"" + file.getName() + "\"");
        
        Integer code = HttpRequestUtil.octetStreamPut(filePath, url, headerMap);
        System.out.println(code);
    }
}

补充一下完整的HttpRequestUtil:

package com.ly.mp.ota.apimanage.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.SecureRandom;
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.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.xml.bind.DatatypeConverter;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
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.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;

import com.alibaba.fastjson.JSONObject;

import ly.mp.project.common.util.LogUtils;


/**
 * @ClassName:HttpRequestUtil
 * @Description: Http请求
 */
public class HttpRequestUtil {
    private String defaultContentEncoding;


    static {
        java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    public HttpRequestUtil() {
        this.defaultContentEncoding = Charset.defaultCharset().name();
    }

    /**
     * 默认的响应字符集
     */
    public String getDefaultContentEncoding() {
        return this.defaultContentEncoding;
    }

    /**
     * 设置默认的响应字符集
     */
    public void setDefaultContentEncoding(String defaultContentEncoding) {
        this.defaultContentEncoding = defaultContentEncoding;
    }

    public static String post(JSONObject json, String url) throws Exception {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(json.toString(), "utf-8");
            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line + '\n');
            }
            result = strber.toString();
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                if (StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            // System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if (null != br) br.close();
            if (null != br) in.close();
            if (null != response) response.close();
            if (null != httpclient) httpclient.close();
        }
        return result;
    }

    public static String post(JSONObject json, String url, Map<String, String> headerMap) throws Exception {
        HttpClientBuilder builder = HttpClientBuilder.create();
        CloseableHttpClient httpclient = builder.build();
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(json.toString(), "utf-8");
            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line + '\n');
            }
            result = strber.toString();
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                if (StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if(br != null) br.close();
            if(in != null) in.close();
            if(response != null) response.close();
            if(httpclient != null) httpclient.close();
        }
        return result;
    }

    public static String post(JSONObject json, String url, Map<String, String> headerMap, String p12Path, String password) throws Exception {
        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLContext sslContext = getSSlContext(p12Path, password);
        builder.setSSLContext(sslContext);
        CloseableHttpClient httpclient = builder.build();
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(json.toString(), "utf-8");
//            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line + '\n');
            }
            result = strber.toString();
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                if (StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if (null != br) br.close();
            if (null != in) in.close();
            if (null != response) response.close();
            if (null != httpclient) httpclient.close();
        }
        return result;
    }

    public static String post(String json, String url, Map<String, String> headerMap, String crt, String privateKey) throws Exception {
        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLConnectionSocketFactory sslf = getSSlContextByCrtAndKey(crt, privateKey);
//      builder.setSSLContext(sslContext);
        builder.setSSLSocketFactory(sslf);
        CloseableHttpClient httpclient = builder.build();
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(json, "utf-8");
//            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line + '\n');
            }
            result = strber.toString();
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                if (StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if (null != br) br.close();
            if (null != in) in.close();
            if (null != response) response.close();
            if (null != httpclient) httpclient.close();
        }
        return result;
    }

    public static String vespaPost(String json, String url, Map<String, String> headerMap, String crt, String privateKey) {
        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLConnectionSocketFactory sslf = getSSlContextByCrtAndKey(crt, privateKey);
//      builder.setSSLContext(sslContext);
        builder.setSSLSocketFactory(sslf);
        CloseableHttpClient httpclient = builder.build();
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(json, "utf-8");
//            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line).append('\n');
            }
            result = strber.toString();
//            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
//                if (StringUtils.isBlank(result)) result = "服务器异常";
//                throw new Exception(result);
//            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            LogUtils.error("调用接口出错:{}",e);
        } finally {
            try {
                if (null != br) {
                    br.close();
                }
                if (null != in) {
                    in.close();
                }
                if (null != response) {
                    response.close();
                }
                if (null != httpclient) {
                    httpclient.close();
                }
            }catch (Exception e){
                LogUtils.error("调用接口出错:{}",e);
            }
        }
        return result;
    }

    public static String vespaPut(String json, String url, Map<String, String> headerMap, String crt, String privateKey) {
        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLConnectionSocketFactory sslf = getSSlContextByCrtAndKey(crt, privateKey);
//      builder.setSSLContext(sslContext);
        builder.setSSLSocketFactory(sslf);
        CloseableHttpClient httpclient = builder.build();
        HttpPut post = new HttpPut(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(json, "utf-8");
//            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line).append('\n');
            }
            result = strber.toString();
//            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
//                if (StringUtils.isBlank(result)) result = "服务器异常";
//                throw new Exception(result);
//            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            LogUtils.error("调用接口出错:{}",e);
        } finally {
            try {
                if (null != br) {
                    br.close();
                }
                if (null != in) {
                    in.close();
                }
                if (null != response) {
                    response.close();
                }
                if (null != httpclient) {
                    httpclient.close();
                }
            }catch (Exception e){
                LogUtils.error("调用接口出错:{}",e);
            }
        }
        return result;
    }

    public static SSLConnectionSocketFactory getSSlContextByCrtAndKey(String crt, String privateKey) {
        SSLConnectionSocketFactory sslsf = null;
        try {
            String crtContent = crt.split("-----BEGIN CERTIFICATE-----\n")[1].split("\n-----END CERTIFICATE-----")[0];
            CertificateFactory factory = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(crtContent)));

            RSAPrivateKey key = (RSAPrivateKey) parseKey(privateKey, null);

            KeyStore keystore = KeyStore.getInstance("JKS");
            keystore.load(null);
            keystore.setCertificateEntry("cert-alias", cert);
            //生成证书的密码,修改为自己的
            keystore.setKeyEntry("key-alias", key, "123456".toCharArray(), new Certificate[]{cert});
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(keystore, "123456".toCharArray());

            //根据你的jdk版本决定是TLS、TLSv1.1、TLSv1.2
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            context.init(kmf.getKeyManagers(), null, null);
            sslsf = new SSLConnectionSocketFactory(context);
        } catch (Exception e) {
            LogUtils.error("getSSlContextByCrtAndKey 异常:{}",e);

        }
        return sslsf;
    }

    public static byte[] formatPkcs1ToPkcs8(String privateKey) throws Exception {
        if (StringUtils.isNotBlank(privateKey)) {
            //将BASE64编码的私钥字符串进行解码
            byte[] encodeByte = org.apache.commons.codec.binary.Base64.decodeBase64(privateKey);

            AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag);    //PKCSObjectIdentifiers.pkcs8ShroudedKeyBag        
//            ASN1Object asn1Object = ASN1Object.fromByteArray(encodeByte);
            ASN1Object asn1Object = ASN1ObjectIdentifier.fromByteArray(encodeByte);
            PrivateKeyInfo privKeyInfo = new PrivateKeyInfo(algorithmIdentifier, asn1Object);
            byte[] pkcs8Bytes = privKeyInfo.getEncoded();

//            String type = "PRIVATE KEY";
//            result = format2PemString(type, pkcs8Bytes); // 格式化为pem多行格式输出
            return Base64.encodeBase64(pkcs8Bytes); // 直接一行字符串输出

        }
        return null;
    }

    /**
     * Parses a Key instance from a PEM representation.
     * <p>
     * When the provided key is encrypted, the provided pass phrase is applied.
     *
     * @param pemString  a PEM representation of a private key (cannot be null or empty)
     * @param passPhrase optional pass phrase (must be present if the private key is encrypted).
     * @return a  Key instance (never null)
     */
    public static Key parseKey(String pemString, String passPhrase) throws IOException {

        if (passPhrase == null) {
            passPhrase = "";
        }
        try (StringReader reader = new StringReader(pemString); //
             PEMParser pemParser = new PEMParser(reader)) {

            final Object object = pemParser.readObject();
            final JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);

            final KeyPair kp;

            if (object instanceof PEMEncryptedKeyPair) {
                // Encrypted key - we will use provided password
                final PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(passPhrase.toCharArray());
                kp = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
            } else if (object instanceof PKCS8EncryptedPrivateKeyInfo) {
                // Encrypted key - we will use provided password
                try {
                    final PKCS8EncryptedPrivateKeyInfo encryptedInfo = (PKCS8EncryptedPrivateKeyInfo) object;
                    final InputDecryptorProvider provider = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passPhrase.toCharArray());
                    final PrivateKeyInfo privateKeyInfo = encryptedInfo.decryptPrivateKeyInfo(provider);
                    return converter.getPrivateKey(privateKeyInfo);
                } catch (PKCSException | OperatorCreationException e) {
                    throw new IOException("Unable to decrypt private key.", e);
                }
            } else if (object instanceof PrivateKeyInfo) {
                return converter.getPrivateKey((PrivateKeyInfo) object);
            } else if (object instanceof SubjectPublicKeyInfo) {
                return converter.getPublicKey((SubjectPublicKeyInfo) object);
            } else {
                // Unencrypted key - no password needed
                kp = converter.getKeyPair((PEMKeyPair) object);
            }
            return kp.getPrivate();
        }
    }

    private static SSLContext getSSlContext(String p12Path, String password) {
        SSLContext sslContext = null;
        try {
            KeyStore kstore = KeyStore.getInstance("PKCS12");
            kstore.load(new FileInputStream(p12Path), password.toCharArray());
            KeyManagerFactory keyFactory = KeyManagerFactory.getInstance("sunx509");
            keyFactory.init(kstore, password.toCharArray());

            sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(keyFactory.getKeyManagers(), null, (SecureRandom) null);
        } catch (Exception e) {
            e.printStackTrace();

        }
        return sslContext;
    }
    
    private static SSLConnectionSocketFactory getSSlContext1(String p12Path, String password) {
        SSLContext sslContext = null;
        SSLConnectionSocketFactory sslsf = null;
        try {
            KeyStore kstore = KeyStore.getInstance("PKCS12");
            kstore.load(new FileInputStream(p12Path), password.toCharArray());
            KeyManagerFactory keyFactory = KeyManagerFactory.getInstance("sunx509");
            keyFactory.init(kstore, password.toCharArray());

         // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(kstore, password.toCharArray())
                    .build();
            // Allow TLSv1 protocol only
            sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"},
                    null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
//            sslContext = SSLContext.getInstance("TLSv1.2");
//            sslContext.init(keyFactory.getKeyManagers(), null, (SecureRandom) null);
        } catch (Exception e) {
            e.printStackTrace();

        }
        return sslsf;
    }

    /**
     * ContentType.URLENCODED.getHeader()
     *
     * @param map
     * @param url
     * @param headerMap
     * @param contentType
     * @return
     * @throws Exception
     */
    public static String post(Map<String, String> map, String url, Map<String, String> headerMap, String contentType) throws Exception {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            List<NameValuePair> nameValuePairs = getNameValuePairList(map);
            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nameValuePairs, "UTF-8");
            /*发送json数据需要设置contentType*/
            urlEncodedFormEntity.setContentType(contentType);
            post.setEntity(urlEncodedFormEntity);
            post.setHeader("Content-Type", contentType);
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line + '\n');
            }
            result = strber.toString();
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                if (StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if(br != null) br.close();
            if(in != null) in.close();
            if(response != null) response.close();
            if(httpclient != null) httpclient.close();
        }
        return result;
    }

    private static List<NameValuePair> getNameValuePairList(Map<String, String> map) {
        List<NameValuePair> list = new ArrayList<>();
        for (String key : map.keySet()) {
            list.add(new BasicNameValuePair(key, map.get(key)));
        }

        return list;
    }

    public static String post(String params, String url, Map<String, String> headerMap) throws Exception {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(params.toString(), "utf-8");
            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line + '\n');
            }
            result = strber.toString();
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                if (StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if(br != null) br.close();
            if(in != null) in.close();
            if(response != null) response.close();
            if(httpclient != null) httpclient.close();
        }
        return result;
    }

    public static String put(JSONObject json, String url, Map<String, String> headerMap) throws Exception {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpPut post = new HttpPut(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringEntity s = new StringEntity(json.toString(), "utf-8");
            s.setContentEncoding("UTF-8");
            /*发送json数据需要设置contentType*/
            s.setContentType("application/json");
            post.setEntity(s);
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line + '\n');
            }
            result = strber.toString();
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                if (StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if(br != null) br.close();
            if(in != null) in.close();
            if(response != null) response.close();
            if(httpclient != null) httpclient.close();
        }
        return result;
    }

    public static String delete(String url, Map<String, String> headerMap) throws Exception {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpDelete post = new HttpDelete(url);
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line + '\n');
            }
            result = strber.toString();
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                if (StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            //System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if(br != null) br.close();
            if(in != null) in.close();
            if(response != null) response.close();
            if(httpclient != null) httpclient.close();
        }
        return result;
    }

    public static String get(JSONObject paramsObj, String url, Map<String, String> headerMap) throws Exception {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        CloseableHttpResponse response = null;
        InputStream in = null;
        BufferedReader br = null;
        String result = "";
        try {
            StringBuffer param = new StringBuffer();
            int i = 0;

            Set<Entry<String, Object>> entries = paramsObj.entrySet();
            for (Entry<String, Object> entry : entries) {
                if (i == 0)
                    param.append("?");
                else
                    param.append("&");
                param.append(entry.getKey()).append("=").append(entry.getValue());
                i++;
            }

            url += param;
            HttpGet post = new HttpGet(url);
//            post.setHeader("Content-Type","application/json;charset=utf-8");

            Set<Entry<String, String>> headerEntries = headerMap.entrySet();
            for (Entry<String, String> headerEntry : headerEntries) {
                post.setHeader(headerEntry.getKey(), headerEntry.getValue());
            }

            response = httpclient.execute(post);
            in = response.getEntity().getContent();
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null) {
                strber.append(line + '\n');
            }
            result = strber.toString();
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                if (StringUtils.isBlank(result)) result = "服务器异常";
                throw new Exception(result);
            }
            //System.out.println("返回数据="+result);
        } catch (Exception e) {
            // System.err.println("调用接口出错::::::::::::"+e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if(br != null) br.close();
            if(in != null) in.close();
            if(response != null) response.close();
            if(httpclient != null) httpclient.close();
        }
        return result;
    }

    public static Integer octetStreamPut(String filePath, String url, Map<String, String> headerMap) throws Exception {
        HttpClientBuilder builder = HttpClientBuilder.create();
//      SSLContext sslContext = getSSlContext(p12Path, password);
//        builder.setSSLContext(sslContext);
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                return true;
            }
        }).build();
        builder.setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext,
                NoopHostnameVerifier.INSTANCE));
        CloseableHttpClient httpclient = builder.build();
        HttpPut put = new HttpPut(url);
        CloseableHttpResponse response = null;
        
        try {
            ContentProducer myContentProducer = new ContentProducer() {
                 @Override
                 public void writeTo(OutputStream out) throws IOException
                 {
                    FileInputStream in = null;
                    
                    try {
                        in = new FileInputStream(new File(filePath));
                        
                        int byteread = 0;
                        byte[] buffer = new byte[1024];
                        while ((byteread = in.read(buffer)) != -1) {
                            out.write(buffer, 0, byteread);
                        }
                    } catch (Exception e) {
                        throw e;
                    } finally {
                        if(in != null) in.close();
                    }
                 }
               };
           put.setHeader("Content-Type", "application/octet-stream");
           Set<Entry<String, String>> headerEntries = headerMap.entrySet();
           for (Entry<String, String> headerEntry : headerEntries) {
               put.setHeader(headerEntry.getKey(), headerEntry.getValue());
           }
            put.setEntity(new EntityTemplate(myContentProducer));
            
            response = httpclient.execute(put);
            LogUtils.info("response.code==={}", response.getStatusLine().getStatusCode());
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED) {
                LogUtils.info("服务器传输异常:{}", response);
                throw new Exception(String.valueOf(response.getStatusLine().getStatusCode()));
            } 
            return response.getStatusLine().getStatusCode();
        } catch (Exception e) {
            throw e;
        } finally {
            if(response != null) response.close();
            if(httpclient != null) httpclient.close();
        }
    }
}

HmacSHA256Util:

package ly.mp.project.common.util;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class HmacSHA256Util {
     /**
     * HmacSHA256算法,返回的结果始终是32位
     * @param key 加密的键,可以是任何数据
     * @param content 待加密的内容
     * @return 加密后的内容
     * @throws Exception
     */
    public static byte[] hmacSHA256(byte[] key,byte[] content) throws Exception {
        Mac hmacSha256 = Mac.getInstance("HmacSHA256");
        hmacSha256.init(new SecretKeySpec(key, 0, key.length, "HmacSHA256"));
        byte[] hmacSha256Bytes = hmacSha256.doFinal(content);
        return hmacSha256Bytes;
    }

    /**
     * 将加密后的字节数组转换成字符串
     *
     * @param b 字节数组
     * @return 字符串
     */
    public  static String byteArrayToHexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b!=null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1)
                hs.append('0');
            hs.append(stmp);
        }
        return hs.toString().toLowerCase();
    }
    /**
     * sha256_HMAC加密
     * @param message 消息
     * @param secret  秘钥
     * @return 加密后字符串
     */
    public static String hmacSHA256(String secret, String message) throws Exception {
        String hash = "";
        Mac hmacSha256 = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        hmacSha256.init(secret_key);
        byte[] bytes = hmacSha256.doFinal(message.getBytes());
        hash = byteArrayToHexString(bytes);
        return hash;
    }

    public static void main(String[] args) {
        String appSecret = "b06c75b58d1701ff470119a4114f8b45";
        String appId = "10000001";
        String timestamp = "1529853639000";

//        HMAC-SHA256(appSecret,appId + timestamp+去除节点间的空格及换行符的请求体)
        String message = appId + timestamp + "<req><orderId>91303183862452</orderId><notifyUrl></notifyUrl><refundTime>2013-03-22 16:25:26</refundTime><refundFee>24.5</refundFee><refundNo>14252414245</refundNo></req>";
        System.out.println("加密前 =========>"+message);
        String str = "";
        try{
            str = HmacSHA256Util.hmacSHA256(appSecret,message);
            System.out.println("加密后 =========>"+str);
        }catch (Exception e){
            System.out.println("Error HmacSHA256 ===========>" + e.getMessage());
        }

    }
}
上一篇下一篇

猜你喜欢

热点阅读