关于JAVA发送Https请求(HttpsURLConnection和HttpURLConnection)

https协议对于开发者而言其实只是多了一步证书验证的过程。这个证书正常情况下被jdk/jre/security/cacerts所管理。里面证书包含两种情况:

1、机构所颁发的被认证的证书,这种证书的网站在浏览器访问时https头显示为绿色如百度

2、个人所设定的证书,这种证书的网站在浏览器里https头显示为红色×,且需要点击信任该网站才能继续访问。而点击信任这一步的操作就是我们在java代码访问https网站时区别于http请求需要做的事情。


所以JAVA发送Https请求有两种情况,三种解决办法:

第一种情况:Https网站的证书为机构所颁发的被认证的证书,这种情况下和http请求一模一样,无需做任何改变,用HttpsURLConnection或者HttpURLConnection都可以

  • public static void main(String[] args) throws Exception{
            URL serverUrl = new URL("https://xxxx");
            HttpURLConnection conn = (HttpURLConnection) serverUrl.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Content-type", "application/json");
            //必须设置false,否则会自动redirect到重定向后的地址
            conn.setInstanceFollowRedirects(false);
            conn.connect();
            String result = getReturn(conn);
        }
    
        /*请求url获取返回的内容*/
        public static String getReturn(HttpURLConnection connection) throws IOException{
            StringBuffer buffer = new StringBuffer();
            //将返回的输入流转换成字符串
            try(InputStream inputStream = connection.getInputStream();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, ConstantInfo.CHARSET);
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);){
                String str = null;
                while ((str = bufferedReader.readLine()) != null) {
                    buffer.append(str);
                }
                String result = buffer.toString();
                return result;
            }
    }

第二种情况:个人所设定的证书,这种证书默认不被信任,需要我们自己选择信任,信任的办法有两种:

A、将证书导入java的运行环境中

  • 从该网站下载或者从网站开发者出获取证书cacert.crt
  • 运行命令将证书导入java运行环境:keytool -import -keystore %JAVA_HOME%\jre\lib\security\cacerts -file cacert.crt -alias xxx
  • 完成。java代码中发送https的请求和http一样,同第一种情况。

B、忽略证书验证过程,忽略之后任何Https协议网站皆能正常访问,同第一种情况

  • import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import javax.net.ssl.X509TrustManager;
    public class MyX509TrustManager implements X509TrustManager {
    
        @Override
        public void checkClientTrusted(X509Certificate certificates[],String authType) throws CertificateException {
        }
    
        @Override
        public void checkServerTrusted(X509Certificate[] ax509certificate,String s) throws CertificateException {
        }
    
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }
    }
  • public static void main(String[] args) throws Exception{
            SSLContext sslcontext = SSLContext.getInstance("SSL","SunJSSE");
            sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()}, new java.security.SecureRandom());
            URL url = new URL("https://xxxx");
            HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
                public boolean verify(String s, SSLSession sslsession) {
                    System.out.println("WARNING: Hostname is not matched for cert.");
                    return true;
                }
            };
            HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
            HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
            //之后任何Https协议网站皆能正常访问,同第一种情况
    }
    

C、java代码中加载证书,必须使用HttpsURLConnection方式

  • 从网站开发者出获取生成证书的密钥库cacert.keystore
  • import java.io.FileInputStream;
    import java.security.KeyStore;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.TrustManagerFactory;
    import javax.net.ssl.X509TrustManager;
    public class MyX509TrustManager implements X509TrustManager {
        /*
         * The default X509TrustManager returned by SunX509.  We'll delegate
         * decisions to it, and fall back to the logic in this class if the
         * default X509TrustManager doesn't trust it.
         */
        X509TrustManager sunJSSEX509TrustManager;
        MyX509TrustManager() throws Exception {
            // create a "default" JSSE X509TrustManager.
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream("cancert.keystore"),
                    "changeit".toCharArray());
            TrustManagerFactory tmf =
                    TrustManagerFactory.getInstance("SunX509", "SunJSSE");
            tmf.init(ks);
            TrustManager tms [] = tmf.getTrustManagers();
                /*
                 * Iterate over the returned trustmanagers, look
                 * for an instance of X509TrustManager.  If found,
                 * use that as our "default" trust manager.
                 */
            for (int i = 0; i < tms.length; i++) {
                if (tms[i] instanceof X509TrustManager) {
                    sunJSSEX509TrustManager = (X509TrustManager) tms[i];
                    return;
                }
            }
                /*
                 * Find some other way to initialize, or else we have to fail the
                 * constructor.
                 */
            throw new Exception("Couldn't initialize");
        }
        /*
         * Delegate to the default trust manager.
         */
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            try {
                sunJSSEX509TrustManager.checkClientTrusted(chain, authType);
            } catch (CertificateException excep) {
                // do any special handling here, or rethrow exception.
            }
        }
        /*
         * Delegate to the default trust manager.
         */
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            try {
                sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
            } catch (CertificateException excep) {
                    /*
                     * Possibly pop up a dialog box asking whether to trust the
                     * cert chain.
                     */
            }
        }
        /*
         * Merely pass this through.
         */
        public X509Certificate[] getAcceptedIssuers() {
            return sunJSSEX509TrustManager.getAcceptedIssuers();
        }
    }
  • public static void main(String[] args) throws Exception{
            SSLContext sslcontext = SSLContext.getInstance("SSL","SunJSSE");
            sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()}, new java.security.SecureRandom());
            URL serverUrl = new URL("https://xxxx");
            HttpsURLConnection conn = (HttpsURLConnection) serverUrl.openConnection();
            conn.setSSLSocketFactory(sslcontext.getSocketFactory());
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Content-type", "application/json");
            //必须设置false,否则会自动redirect到重定向后的地址
            conn.setInstanceFollowRedirects(false);
            conn.connect();
            String result = getReturn(conn);
        }
    
        /*请求url获取返回的内容*/
        public static String getReturn(HttpsURLConnection connection) throws IOException{
            StringBuffer buffer = new StringBuffer();
            //将返回的输入流转换成字符串
            try(InputStream inputStream = connection.getInputStream();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, ConstantInfo.CHARSET);
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);){
                String str = null;
                while ((str = bufferedReader.readLine()) != null) {
                    buffer.append(str);
                }
                String result = buffer.toString();
                return result;
            }
    }
    
    


发布了4 篇原创文章 · 获赞 12 · 访问量 3万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览