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

时间:2021-06-19 21:10:52

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

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

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

 

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

 

 

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

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

 

  • [java]  view plain  copy
     
    1. public static void main(String[] args) throws Exception{  
    2.         URL serverUrl = new URL("https://xxxx");  
    3.         HttpURLConnection conn = (HttpURLConnection) serverUrl.openConnection();  
    4.         conn.setRequestMethod("GET");  
    5.         conn.setRequestProperty("Content-type", "application/json");  
    6.         //必须设置false,否则会自动redirect到重定向后的地址  
    7.         conn.setInstanceFollowRedirects(false);  
    8.         conn.connect();  
    9.         String result = getReturn(conn);  
    10.     }  
    11.   
    12.     /*请求url获取返回的内容*/  
    13.     public static String getReturn(HttpURLConnection connection) throws IOException{  
    14.         StringBuffer buffer = new StringBuffer();  
    15.         //将返回的输入流转换成字符串  
    16.         try(InputStream inputStream = connection.getInputStream();  
    17.             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, ConstantInfo.CHARSET);  
    18.             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);){  
    19.             String str = null;  
    20.             while ((str = bufferedReader.readLine()) != null) {  
    21.                 buffer.append(str);  
    22.             }  
    23.             String result = buffer.toString();  
    24.             return result;  
    25.         }  
    26. }  

 

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

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

 

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

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

 

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

 

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

 

 

  • 从网站开发者出获取生成证书的密钥库cacert.keystore
  • [java]  view plain  copy
     
    1. import java.io.FileInputStream;  
    2. import java.security.KeyStore;  
    3. import java.security.cert.CertificateException;  
    4. import java.security.cert.X509Certificate;  
    5. import javax.net.ssl.TrustManager;  
    6. import javax.net.ssl.TrustManagerFactory;  
    7. import javax.net.ssl.X509TrustManager;  
    8. public class MyX509TrustManager implements X509TrustManager {  
    9.     /* 
    10.      * The default X509TrustManager returned by SunX509.  We'll delegate 
    11.      * decisions to it, and fall back to the logic in this class if the 
    12.      * default X509TrustManager doesn't trust it. 
    13.      */  
    14.     X509TrustManager sunJSSEX509TrustManager;  
    15.     MyX509TrustManager() throws Exception {  
    16.         // create a "default" JSSE X509TrustManager.  
    17.         KeyStore ks = KeyStore.getInstance("JKS");  
    18.         ks.load(new FileInputStream("cancert.keystore"),  
    19.                 "changeit".toCharArray());  
    20.         TrustManagerFactory tmf =  
    21.                 TrustManagerFactory.getInstance("SunX509", "SunJSSE");  
    22.         tmf.init(ks);  
    23.         TrustManager tms [] = tmf.getTrustManagers();  
    24.             /* 
    25.              * Iterate over the returned trustmanagers, look 
    26.              * for an instance of X509TrustManager.  If found, 
    27.              * use that as our "default" trust manager. 
    28.              */  
    29.         for (int i = 0; i < tms.length; i++) {  
    30.             if (tms[i] instanceof X509TrustManager) {  
    31.                 sunJSSEX509TrustManager = (X509TrustManager) tms[i];  
    32.                 return;  
    33.             }  
    34.         }  
    35.             /* 
    36.              * Find some other way to initialize, or else we have to fail the 
    37.              * constructor. 
    38.              */  
    39.         throw new Exception("Couldn't initialize");  
    40.     }  
    41.     /* 
    42.      * Delegate to the default trust manager. 
    43.      */  
    44.     public void checkClientTrusted(X509Certificate[] chain, String authType)  
    45.             throws CertificateException {  
    46.         try {  
    47.             sunJSSEX509TrustManager.checkClientTrusted(chain, authType);  
    48.         } catch (CertificateException excep) {  
    49.             // do any special handling here, or rethrow exception.  
    50.         }  
    51.     }  
    52.     /* 
    53.      * Delegate to the default trust manager. 
    54.      */  
    55.     public void checkServerTrusted(X509Certificate[] chain, String authType)  
    56.             throws CertificateException {  
    57.         try {  
    58.             sunJSSEX509TrustManager.checkServerTrusted(chain, authType);  
    59.         } catch (CertificateException excep) {  
    60.                 /* 
    61.                  * Possibly pop up a dialog box asking whether to trust the 
    62.                  * cert chain. 
    63.                  */  
    64.         }  
    65.     }  
    66.     /* 
    67.      * Merely pass this through. 
    68.      */  
    69.     public X509Certificate[] getAcceptedIssuers() {  
    70.         return sunJSSEX509TrustManager.getAcceptedIssuers();  
    71.     }  
    72. }  
  • [java]  view plain  copy
     
    1.   
    [java]  view plain  copy
     
    1. public static void main(String[] args) throws Exception{  
    2.         SSLContext sslcontext = SSLContext.getInstance("SSL","SunJSSE");  
    3.         sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()}, new java.security.SecureRandom());  
    4.         URL serverUrl = new URL("https://xxxx");  
    5.         HttpsURLConnection conn = (HttpsURLConnection) serverUrl.openConnection();  
    6.         conn.setSSLSocketFactory(sslcontext.getSocketFactory());  
    7.         conn.setRequestMethod("GET");  
    8.         conn.setRequestProperty("Content-type", "application/json");  
    9.         //必须设置false,否则会自动redirect到重定向后的地址  
    10.         conn.setInstanceFollowRedirects(false);  
    11.         conn.connect();  
    12.         String result = getReturn(conn);  
    13.     }  
    14.   
    15.     /*请求url获取返回的内容*/  
    16.     public static String getReturn(HttpsURLConnection connection) throws IOException{  
    17.         StringBuffer buffer = new StringBuffer();  
    18.         //将返回的输入流转换成字符串  
    19.         try(InputStream inputStream = connection.getInputStream();  
    20.             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, ConstantInfo.CHARSET);  
    21.             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);){  
    22.             String str = null;  
    23.             while ((str = bufferedReader.readLine()) != null) {  
    24.                 buffer.append(str);  
    25.             }  
    26.             String result = buffer.toString();  
    27.             return result;  
    28.         }  
    29. }