https,http综合集成

package com.example.demo.utils.http;

import javax.crypto.Cipher;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Date;


public class CertificateUtils {
    /**
     * 实例化证书工厂(双向认证)
     * @param keyStorePwd 密钥库及信任库密码(一样的)
     * @param keyStorePath 密钥库路径
     * @param trustKeyStorePath 信任库路径
     * @param sunX509 算法名称 (该方式<KeyManagerFactory>默认填写SunX509,通过CertificateFactory获取证书写X.509)
     * @param keyStoreType 密钥库类型 pkcs12或者JKS
     * @param ssl 请求协议的标准名称.SSL或STL
     * @return
     */
    public static SSLSocketFactory getSf(String keyStorePwd, String keyStorePath, String trustKeyStorePath,
                                         String sunX509,String keyStoreType,String ssl) throws Exception {
        // 初始化密钥库 sunX509 KeyManagerFactory.getDefaultAlgorithm()
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(sunX509);
        KeyStore keyStore = getKeyStore(keyStorePath, keyStorePwd,keyStoreType);
        keyManagerFactory.init(keyStore, keyStorePwd.toCharArray());

        // 初始化信任库
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(sunX509);
        KeyStore trustkeyStore = getKeyStore(trustKeyStorePath, keyStorePwd,keyStoreType);
        trustManagerFactory.init(trustkeyStore);


        // 初始化SSL上下文
        SSLContext ctx = SSLContext.getInstance(ssl);
        ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
        SSLSocketFactory sf = ctx.getSocketFactory();

        return sf;
    }
    /**
     * 实例化证书工厂(单向认证)
     * @return
     */
    public static SSLSocketFactory getSf() throws Exception {
        InputStream ins = new FileInputStream("aaa.cer");
        CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");
        java.security.cert.Certificate cer = cerFactory.generateCertificate(ins);
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());   //问2
        keyStore.load(null, null);
        keyStore.setCertificateEntry("trust", cer);
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        sslContext.init( null, trustManagerFactory.getTrustManagers(), new SecureRandom());

        SSLSocketFactory sf = sslContext.getSocketFactory();
        return sf;
    }
    /**
     * 获取密钥库
     */
    private static KeyStore getKeyStore(String keyStorePath, String password,String keyStoreType) throws Exception {
        FileInputStream fis = new FileInputStream(keyStorePath);
        KeyStore ks = KeyStore.getInstance(keyStoreType);
        ks.load(fis, password.toCharArray());
        fis.close();

        return ks;
    }

    /**
     *  获得证书(通过密钥库获得证书)
     * @param keystorePath 密钥库路径
     * @param keystorePwd  密钥库密码
     * @param keystoreType 密钥库类型
     * @param keyAlias     密钥库别名
     * @return
     */
    private static X509Certificate getCert(String keystorePath, String keystorePwd, String keystoreType, String keyAlias)
            throws Exception {
        KeyStore keyStore = getKeyStore(keystorePath, keystorePwd, keystoreType);
        X509Certificate x509Certificate = (X509Certificate) keyStore.getCertificate(keyAlias);
        return x509Certificate;
    }
    /**
     * 获得证书Certificate(通过证书工厂取得证书) 暂未使用
     *
     * @param certificatePath
     * @return
     * @throws Exception
     */
    private static X509Certificate getCertificate(String certificatePath)
            throws Exception {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        FileInputStream in = new FileInputStream(certificatePath);
        X509Certificate certificate =(X509Certificate) certificateFactory.generateCertificate(in);
        in.close();
        return certificate;
    }

    /**
     *  获得证书的base64字符串
     * @param keystorePath 证书文件路径
     * @param keystorePwd  证书文件密码
     * @param keystoreType 证书文件类型
     * @param keyAlias     证书文件别名
     * @return
     */
    public static String getBase64Cert(String keystorePath, String keystorePwd, String keystoreType, String keyAlias){
        X509Certificate x509Certificate = null;
        try {
            x509Certificate = getCert(keystorePath,keystorePwd,keystoreType,keyAlias);
            byte[] bs = x509Certificate.getEncoded();
            String merchantCert = Base64.getEncoder().encodeToString(bs);
            return merchantCert;
        } catch (Exception e) {
           return null;
        }
    }

    /**
     * 使用私钥对数据进行加密(请求发送数据的时候使用)
     * @param info 需要校验的请求参数的json字符串或xml
     * @param keyStorePath 密钥库路径
     * @param keystorePwd  密钥库密码
     * @param keyStoreType 密钥库类型
     * @param prtAlias 密钥库别名
     * @param mrSigAlgName 签名方式 SHA256WithRSA 或 MD5 或 RSA
     * @return
     */
    public static String encodeBySK(String info,String keyStorePath, String keystorePwd,String keyStoreType,String prtAlias,String mrSigAlgName) {
        try {
            /**
             * getKeyStore(keyStorePath, keystorePwd)
             * PrivateKey key = (PrivateKey) ks.getKey(alias,aliasPwd.toCharArray());
             * 一般情况下证书库密码与别名密码不一样
             */
            KeyStore keyStore = getKeyStore(keyStorePath,keystorePwd,keyStoreType);
            PrivateKey pk = (PrivateKey) keyStore.getKey(prtAlias, keystorePwd.toCharArray());
            Signature sign = Signature.getInstance(mrSigAlgName);
            sign.initSign(pk);
            sign.update(info.getBytes());
            byte[] signed = sign.sign();
            String signValue = Base64.getEncoder().encodeToString(signed);
            return signValue;
        }catch (Exception e){
            return null;
        }
    }

    /**
     * 使用私钥对数据进行解密(用于接受参数解密) 暂时未启用
     * @param data
     * @param keyStorePath
     * @param keyStorePwd
     * @param prtAlias
     * @param keyStoreType
     * @return
     */
    @Deprecated
    public static byte[] decodeBySK(String data, String keyStorePath, String keyStorePwd, String prtAlias, String keyStoreType) {
        try {
            // 取得私钥
            KeyStore keyStore = getKeyStore(keyStorePath,keyStorePwd,keyStoreType);
            PrivateKey pk = (PrivateKey) keyStore.getKey(prtAlias, keyStorePwd.toCharArray());
            // 对数据加密
            Cipher cipher = Cipher.getInstance(pk.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, pk);
            return cipher.doFinal(data.getBytes());
        }catch (Exception e){
            return null;
        }
    }
    /**
     * 公钥加密 暂时未启用
     * @param data 签名的json参数或xml
     * @param certificatePath 证书文件路径
     * @return
     * @throws Exception
     */
    @Deprecated
    public static String encryptByPK(String data, String certificatePath) {
        try {
            // 取得公钥
            X509Certificate certificate = getCertificate(certificatePath);
            PublicKey publicKey = certificate.getPublicKey();
            // 对数据加密
            Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return new String(cipher.doFinal(data.getBytes()));
        }catch (Exception e){
            return null;
        }
    }

    /**
     * 公钥解密 (暂时未启用)
     * @param data 签名数据
     * @param certificatePath 证书文件路径
     * @return
     * @throws Exception
     */
    @Deprecated
    public static String decryptByPK(String data, String certificatePath) {
        try{
            // 取得公钥
            X509Certificate certificate = getCertificate(certificatePath);
            PublicKey publicKey = certificate.getPublicKey();
            // 对数据加密
            Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return new String(cipher.doFinal(data.getBytes()));
        }catch (Exception e){
            return null;
        }
    }

    /**
     * 验证证书是否过期 暂时未启用
     * @param certificatePath
     * @return
     */
    @Deprecated
    public static boolean verifyCertificate(String certificatePath){
        boolean status = true;
        try{
            X509Certificate x509Certificate=getCertificate(certificatePath);
            x509Certificate.checkValidity(new Date());
        }catch (Exception e){
            status = false;
        }
        return status;
    }

    /**
     * 验证证书是否过期 暂时未启用
     * @return
     */
    @Deprecated
    public static boolean verifyCertificate(String keyStorePath, String alias, String password,String keyStoreType){
        boolean status = true;
        try{
            X509Certificate x509Certificate=getCert(keyStorePath,password,keyStoreType,alias);
            x509Certificate.checkValidity(new Date());
        }catch (Exception e){
            status = false;
        }
        return status;
    }
}
package com.example.demo.utils.http;

import javax.net.ssl.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

import static com.example.demo.configs.CertConfigUtils.*;

public class URLConnect {
    /**
     * 获取http请求链接
     * @return connection
     */
    public static HttpURLConnection httpCollect(String uri,String methods) throws Exception {
        methods = methods.toUpperCase(); // 将小写全部转换为大写
        URL url = new URL(uri); // 创建链接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 通过远程url连接对象打开一个连接,强转成httpURLConnection类
        connection.setRequestMethod(methods); // 设置连接方式:get/post
        return connection;
    }

    /**
     * 获取不需要验证的https请求
     * @return
     */
    public static HttpsURLConnection notVerifyHttpsCollect(String uri,String methods) throws Exception{
        /**
         * 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
         */
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString)  {
                // TODO: 2018/9/10
                /**
                 * 该方法检查客户端的证书,若不信任该证书则抛出异常。
                 * 由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。
                 * JSSE中,默认的信任管理器类为TrustManager
                 */
            }

            @Override
            public void checkServerTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) {
                // TODO: 2018/9/10
                /**
                 * 该方法检查服务器的证书,若不信任该证书同样抛出异常。
                 * 通过自己实现该方法,可以使之信任我们指定的任何证书。
                 * 在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。
                 */
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                // TODO: 2018/9/10
                // 返回受信任的X509证书数组。
                return null;
            }
        };

        // 创建SSLContext对象,并使用我们指定的信任管理器初始化
        TrustManager[] tm = { trustManager };
        SSLContext ctx = SSLContext.getInstance("SSL","SunJSSE"); // SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(null, tm, new SecureRandom()); // ctx.init(new KeyManager[0],tm, new SecureRandom());

        // 从上述SSLContext对象中得到SSLSocketFactory对象
        SSLSocketFactory ssf = ctx.getSocketFactory();

        // 创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
        URL url = new URL(uri);
        HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection();
        httpsConn.setSSLSocketFactory(ssf);


        httpsConn.setHostnameVerifier((arg0,arg1) -> true);
        httpsConn.setRequestMethod(methods);
        return httpsConn;
    }
    public static HttpsURLConnection httpsCollect(String uri,String methods){
        try{
            // eg: 123456,D:/crt/abc.pfx,D:/crt/abd.pfx,JKS,SunX509,pkcs12,SSL
            SSLSocketFactory ssf =  null;
            if(isCert == 2){
                ssf = CertificateUtils.getSf(mrKeyPwd,mrKeyAlias,trustPath,sunX509,mrKeystoreType,SSL);
            }else if(isCert == 3){
                CertificateUtils.getSf();
            }else {
                return null;
            }
            URL url = new URL(uri);
            HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection();
            httpsConn.setSSLSocketFactory(ssf);
            httpsConn.setHostnameVerifier((arg0,arg1) -> true);
            httpsConn.setRequestMethod(methods);
            return httpsConn;
        }catch (Exception e){
            return null;
        }
    }
    /**
     * 设置请求头
     * @throws Exception
     */
    public static URLConnection doService(String uri,String method) throws Exception {
        URLConnection conn = null;
        if(uri.indexOf("https://") != -1){
            if(isCert ==1){
                conn=notVerifyHttpsCollect(uri,method);
            }else {
                conn = httpsCollect(uri,method);
            }
        }else {
            conn = httpCollect(uri,method);
        }
        conn.setConnectTimeout(8000); // 设置连接主机服务器的超时时间:8秒
        conn.setReadTimeout(8000); // 设置读取远程返回的数据时间:8秒
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("accept", "*/*");
        conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

        // 处理post请求参数
        if(method.equals("POST")){
            conn.setDoInput(true);
            conn.setDoOutput(true); // 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
            conn.setUseCaches(false); // post请求缓存设为false
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");//参数请求格式 或者 application/x-www-form-urlencoded;charset=utf-8
            /**
             * String contentType = conn.getHeaderField("Content-Type"); 通过getHeaderField()方法可以读取响应头
             * conn.setRequestProperty("Authorization", "token 111"); 设置鉴权信息:Authorization: token 111(即添加token)
             * conn.setRequestProperty("Cookie",StringUtils.join(cookieManager.getCookieStore().getCookies(), ";")); 添加cookie
             * String cookiesHeader = conn.getHeaderField("Set-Cookie");List<HttpCookie> cookies = HttpCookie.parse(cookiesHeader); 获取cookie
             * Optional<HttpCookie> usernameCookie = cookies.stream().findAny().filter(cookie -> cookie.getName().equals("username"));检查cookie中是否含有username
             * connection.getResponseCode() 得到响应码 200 500 等  需要写在子类中
             * conn.setInstanceFollowRedirects(false); 处理重定向  需要写在子类中
             */
        }
        return conn;
    }
}
package com.example.demo.utils.http;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URLConnection;

public class URLClient {
    private  static Logger log = LoggerFactory.getLogger(URLClient.class);

    /**
     * 发送http或https类型的get请求
     * @param uri
     * @return
     */
    public static String doGet(String uri) {
        return httpRequest(uri,"GET",null);
    }

    /**
     * 发送http或https类型的post请求(忽略验证的https请求)
     * @param uri
     * @param outputStr
     * @return
     */
    public static String doPost(String uri, String outputStr) {
        return httpRequest(uri,"POST",outputStr);
    }


    private static String httpRequest(String uri,String method,String outputStr){
        try {
            URLConnection conn =URLConnect.doService(uri,method);

            // 如果请求参数不为空
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            StringBuffer buffer = new StringBuffer();
            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            // 关闭链接
            if(conn instanceof HttpURLConnection){
                ((HttpURLConnection)conn).disconnect();
            }else {
                ((HttpsURLConnection)conn).disconnect();
            }
            return buffer.toString();
        } catch (Exception e) {
            log.error("http或者https请求异常,请留意错误信息");
            return null;
        }
    }

}
package com.example.demo.configs;

import java.io.IOException;
import java.util.Properties;

public class CertConfigUtils {

    private static Properties props = new Properties();
    public static Integer isCert = 1;
    // 客户端密码
    public static String mrKeyPwd = null;
    // 客户端别名
    public static String mrKeyAlias = null;
    // 客户端路径
    public static String mrKeyPath = null;
    // 信任的文件
    public static String trustPath = null;


    public static String mrSigAlgName = "SHA256WithRSA";
    public static String sunX509 = "SunX509";
    public static String mrKeystoreType = "pkcs12";
    public static String SSL = "SSL";
    static {

        try {
            props.load(CertConfigUtils.class.getClassLoader().getResourceAsStream("cert_config.properties"));
            mrKeyPwd = props.getProperty("mrKeyPwd");
            mrKeyAlias = props.getProperty("mrKeyAlias");
            mrKeyPath =CertConfigUtils.class.getClassLoader().getResource(props.getProperty("mrKeyPath")).getPath().substring(1);
            trustPath = props.getProperty("trustPath");
        } catch (IOException e) {
            isCert = 1;
        }
    }

}

使用方法

1.将以上4个对象导入到项目中
2.如果是http请求
String result = URLClient.doPost(uri,request.toString());
3.不需要验证的https请求:
String result = URLClient.doPost(uri,request.toString())
4.如果是单项认证的https请求
- 设置CertConfigUtils.isCert=3
- 放置证书文件到目录下(一般为crt格式,cer格式)
- 创建cert_config.properties配置文件并配置证书路径
- 在里面写下trustPath的路径
- String result = URLClient.doPost(uri,request.toString())
5.如果是双向认证的https
- 设置CertConfigUtils.isCert=4
- 放置证书文件到目录下(4个文件。s.crt,s.store,m.crt,m.store)
- 创建cert_config.properties配置文件,配置路径,公钥,私钥
- String result = URLClient.doPost(uri,request.toString())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值