詳解Java如何向http/https接口發(fā)出請求
用Java發(fā)送web請求所用到的包都在java.net
下,在具體使用時可以用如下代碼,你可以把它封裝成一個工具類
import javax.net.ssl.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; public class Testt { /* HostnameVerifier 是一個Java接口 其中的verify方法用來在下面的類中提供主機名的SSL校驗 這里個人用不做具體校驗所有的主機名都給過 */ final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() { public boolean verify(String arg0, SSLSession arg1) { return true; } }; /* trustAllHosts方法 方法創(chuàng)建了一個 TrustManager 接口的匿名實現(xiàn) 它是用來檢查證書的,無論是服務(wù)器證書還是客戶端證書 這通過重寫 checkServerTrusted 和 checkClientTrusted 方法為空 不做任何檢查 */ public static void trustAllHosts() { TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[] {}; } public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } } }; /* SSLContext 使用上述的 TrustManager 初始化一個 SSLContext 實例 并將其設(shè)置為 HttpsURLConnection 的默認(rèn) SSLSocketFactory 這允許 HttpsURLConnection 信任所有SSL證書 TLS是握手協(xié)議的一種 */ try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { e.printStackTrace(); } } /** * 發(fā)出請求的具體方法 * @param urlPath https協(xié)議接口的路徑 https://xxxxxx * @param Json 發(fā)出請求需要攜帶的參數(shù),需要是Json格式 * @return */ public static String doPostToJson(String urlPath, String Json) { String result = ""; BufferedReader reader = null; HttpURLConnection conn = null; try { /* 掉用上面的靜態(tài)方法,使得請求發(fā)出時,作為調(diào)用者的我們對服務(wù)端所擁有的任何https證書都是兼容的 這里說一句題外話:一般情況下,作為接口使用者trustAllHosts方法里面的代碼是不變的,因為你作為使用者 總沒道理說讓人家服務(wù)端兼容你什么,除非你是證書的使用者,不過這種情況會有證書廠商 告訴你如何做,不得不說廠商服務(wù)是個好東西 */ trustAllHosts(); URL url = new URL(urlPath); /* 如果協(xié)議是 https,則使用 HttpsURLConnection 并設(shè)置 HostnameVerifier 為 DO_NOT_VERIFY。 否則,使用 HttpURLConnection */ if (url.getProtocol().toLowerCase().equals("https")) { HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection(); httpsConn.setHostnameVerifier(DO_NOT_VERIFY); conn = httpsConn; } else { conn = (HttpURLConnection) url.openConnection(); } // 設(shè)置請求以POST形式發(fā)出 conn.setRequestMethod("POST"); // 是否攜帶請求提,POST和GET請求必須為true conn.setDoOutput(true); // 是否會獲取服務(wù)端的響應(yīng),默認(rèn)是true conn.setDoInput(true); //禁用緩存 conn.setUseCaches(false); // Keep-Alive告訴服務(wù)端對已有的TCP連接保持一定時間的活性,以保障后續(xù)發(fā)出的請求不需要建立新的TCP連接,從而減少網(wǎng)絡(luò)開銷 conn.setRequestProperty("Connection", "Keep-Alive"); //字符集,這個配置不是標(biāo)準(zhǔn)的請求頭,但是有些妖孽系統(tǒng)會讀取這個 conn.setRequestProperty("Charset", "UTF-8"); // 這個是請求格式,告訴服務(wù)端這個請求發(fā)送的是Json數(shù)據(jù)以及字符集 conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // 告訴服務(wù)端,相應(yīng)格式也希望是json格式 conn.setRequestProperty("accept", "application/json"); //如果參數(shù)不為空則將參數(shù)以字節(jié)數(shù)流的方式寫入請求體里面 if (Json != null) { byte[] writebytes = Json.getBytes(); conn.setRequestProperty("Content-Length", String.valueOf(writebytes.length)); OutputStream outwritestream = conn.getOutputStream(); outwritestream.write(Json.getBytes()); outwritestream.flush(); outwritestream.close(); } //讀取響應(yīng),相應(yīng)數(shù)據(jù)也是一個json if (conn.getResponseCode() == 200) { reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); result = reader.readLine(); } } catch (Exception e) { e.printStackTrace(); } finally { //讀取相應(yīng)用的輸入流需要在這里關(guān)閉,而寫入請求參數(shù)的輸出流是隨用隨關(guān)的 if (reader != null) { try { reader.close(); conn.disconnect(); } catch (IOException e) { e.printStackTrace(); } } } return result; } }
對于上面的代碼,重點要說明的第一點是HostnameVerifier
接口提供的方法,它主要用于訪問https協(xié)議下的接口時,驗證當(dāng)前已和你建立連接的hostname(主機名)和連接的SSLSession(SSL會話)證書是否匹配,防止中間人攻擊,比如可以如下操作
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import java.io.IOException; import java.net.URL; public class HostnameVerifierExample { public static void main(String[] args) { try { // 創(chuàng)建一個URL對象 URL url = new URL("https://xxxxx"); // 打開HTTPS連接 HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); // 設(shè)置自定義的HostnameVerifier HostnameVerifier customVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { // 在這里實現(xiàn)你的驗證邏輯 // 例如,你可以比較hostname和session中的證書信息 // 為了簡單起見,這里我們直接接受任何主機名(不推薦這樣做,有安全風(fēng)險) // 在實際應(yīng)用中,你應(yīng)該根據(jù)你的安全策略來實現(xiàn)這個邏輯 // 比如,你可以檢查hostname是否與你預(yù)期的服務(wù)器主機名匹配 // 或者,你可以使用HttpsURLConnection.getDefaultHostnameVerifier()來獲取默認(rèn)的驗證器,并基于它的結(jié)果進(jìn)行擴(kuò)展 // 這是一個不安全的示例,僅用于說明如何使用verify方法 // 在實際應(yīng)用中,你應(yīng)該避免這樣做 return true; // 更安全的做法可能是這樣的: // if ("expected.hostname".equals(hostname)) { // return true; // } else { // HostnameVerifier defaultVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); // return defaultVerifier.verify(hostname, session); // } } }; // 設(shè)置自定義的HostnameVerifier到連接中 connection.setHostnameVerifier(customVerifier); // 繼續(xù)處理HTTPS連接,比如讀取響應(yīng)等 // ... // 關(guān)閉連接 connection.disconnect(); } catch (IOException e) { e.printStackTrace(); } } }
第二是trustAllHosts方法里面的東西,TrustManager是用來實現(xiàn)證書驗證的類,X509TrustManager是X.509 證書的驗證實現(xiàn),通俗的講是一個基礎(chǔ)的證書,因此我上面的代碼中也說了,如果你是正式的https證書使用者,會有廠商服務(wù)告訴你怎么驗證證書,在X509TrustManager 中提供了三個方法
getAcceptedIssuers():返回此信任管理器接受的發(fā)行者證書(根證書或中間證書)數(shù)組。在上面的代碼中,這個方法返回了一個空數(shù)組,意味著它不做任何特定的發(fā)行者證書獲取
checkServerTrusted(X509Certificate[] certs, String authType):驗證服務(wù)器提供的證書鏈?zhǔn)欠窨尚?。在代碼中,這個方法被空實現(xiàn)了,意味著不會進(jìn)行任何驗證。
checkClientTrusted(X509Certificate[] certs, String authType):驗證客戶端提供的證書鏈?zhǔn)欠窨尚牛ㄔ谛枰蛻舳俗C書的情況下)。同樣,在代碼中,這個方法也被空實現(xiàn)了
到此這篇關(guān)于詳解Java如何向http/https接口發(fā)出請求的文章就介紹到這了,更多相關(guān)Java https接口發(fā)出請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring5學(xué)習(xí)之基礎(chǔ)知識總結(jié)
這篇文章主要介紹了Spring5學(xué)習(xí)之基礎(chǔ)知識總結(jié),文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-05-05Java數(shù)據(jù)結(jié)構(gòu)之簡單鏈表的定義與實現(xiàn)方法示例
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之簡單鏈表的定義與實現(xiàn)方法,簡單描述了鏈接的概念、原理,并結(jié)合實例形式分析了java定義與使用鏈表的相關(guān)步驟與操作技巧,需要的朋友可以參考下2017-10-10SpringMVC @RequestMapping注解應(yīng)用方法示例講解
通過@RequestMapping注解可以定義不同的處理器映射規(guī)則,下面這篇文章主要給大家介紹了關(guān)于SpringMVC中@RequestMapping注解用法的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09Spring Boot Mail QQ企業(yè)郵箱無法連接解決方案
這篇文章主要介紹了Spring Boot Mail QQ企業(yè)郵箱無法連接解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09