本文主要是介绍详解Java如何向http/https接口发出请求,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...
用Java发送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.CertificateEjavascriptxception; 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方法 方法创建了一个 TrustManager 接口的匿名实现 它是用来检查证书的,无论是服务器证书还是客户端证书 这通过重写 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 实例 并将其设置为 HttpsURLConnection 的默认 SSLSocketFactory 这允许 HttpsURLConnection 信任所有SSL证书 TLS是握手协议的一种 */ try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { e.printStackTrace(); } } /** * 发出请求的具体方法 * @param urlPath https协议接口的路径 https://xxxxxx * @param json 发出请求需要携带的参数,需要是Json格式 * @return */ public static String doPostToJson(String urlPath, String Json) { String result = ""; BufferedReader reader = null; HttpURLConnection conn = null; try { /* 掉用上面的静态方法,使得请求发出时,作为调用者的我们对服务端所拥有的任何https证书都是兼容的 这里说一句题外话:一般情况下,作为接口使用者trustAllHosts方法里面的代码是不变的,因为你作为使用者 总没道理说让人家服务端兼容你什么,除非你是证书的使用者,不过这种情况会有证书厂商 告诉你如何做,不得不说厂商服务是个好东西 */ trustAllHosts(); URL url = new URL(urlPath); /* 如果协议是 https,则使用 HttpsURLConnection 并设置 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(); } // 设置请求以POST形式发出 conn.setRequestMethod("POST"); // 是否携带请求提,POST和GET请求必须为true conn.setDoOutput(true); // 是否会获取服务端China编程的响应,默认是true conn.setDoInput(true); //禁用缓存 conn.setUseCaches(false); // Keep-Alive告诉服务端对已有的TCP连接保持一定时间的活性,以保障后续发出的请求不需要建立新的TCP连接,从而减少网络开销 conn.setRequestProperty("Connection", "Keep-Alive"); //字符集,这个配置不是标准的请求头,但是有些妖孽系统会读取这个 conn.setRequestProperty("Charset", "UTF-8"); // 这个是请求格式,告诉服务端这个请求发送的是Json数据以及字符集 conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // 告诉服务端,相应格式也希望是json格式 conn.setRequestProperty("accept", "application/json"); //如果参数不为空则将参数以字节数流的方式写入请求体里面 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(); } android //读取响应,相应javascript数据也是一个json if (conn.getResponseCode() == 200) { reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); result = reader.readLine(); } } catch (Exception e) { e.printStackTrace(); } finally { //读取相应用的输入流需要在这里关闭,而写入请求参数的输出流是随用随关的 if (reader != null) { try { reader.close(); conn.disconnect(); } catch (IOException e) { e.printStackTrace(); } } } return result; } }
对于上面的代码,重点要说明的第一点是HostnameVerifier
接口提供的方法,它主要用于访问https协议下的接口时,验证当前已和你建立连接的hostname(主机名)和连接的SSLSession(SSL会话)证书是否匹配,防止中间人攻击,比如可以如下操作
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import java.io.IOException; importpython java.net.URL; public class HostnameVerifierExample { public static void main(String[] args) { try { // 创建一个URL对象 URL url = new URL("https://xxxxx"); // 打开HTTPS连接 HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); // 设置自定义的HostnameVerifier HostnameVerifier customVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { // 在这里实现你的验证逻辑 // 例如,你可以比较hostname和session中的证书信息 // 为了简单起见,这里我们直接接受任何主机名(不推荐这样做,有安全风险) // 在实际应用中,你应该根据你的安全策略来实现这个逻辑 // 比如,你可以检查hostname是否与你预期的服务器主机名匹配 // 或者,你可以使用HttpsURLConnection.getDefaultHostnameVerifier()来获取默认的验证器,并基于它的结果进行扩展 // 这是一个不安全的示例,仅用于说明如何使用verify方法 // 在实际应用中,你应该避免这样做 return true; // 更安全的做法可能是这样的: // if ("expected.hostname".equals(hostname)) { // return true; // } else { // HostnameVerifier defaultVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); // return defaultVerifier.verify(hostname, session); // } } }; // 设置自定义的HostnameVerifier到连接中 connection.setHostnameVerifier(customVerifier); // 继续处理HTTPS连接,比如读取响应等 // ... // 关闭连接 connection.disconnect(); } catch (IOException e) { e.printStackTrace(); } } }
第二是trustAllHosts方法里面的东西,TrustManager是用来实现证书验证的类,X509TrustManager是X.509 证书的验证实现,通俗的讲是一个基础的证书,因此我上面的代码中也说了,如果你是正式的https证书使用者,会有厂商服务告诉你怎么验证证书,在X509TrustManager 中提供了三个方法
getAcceptedIssuers():返回此信任管理器接受的发行者证书(根证书或中间证书)数组。在上面的代码中,这个方法返回了一个空数组,意味着它不做任何特定的发行者证书获取
checkServerTrusted(X509Certificate[] certs, String authType):验证服务器提供的证书链是否可信。在代码中,这个方法被空实现了,意味着不会进行任何验证。
checkClientTrusted(X509Certificate[] certs, String authType):验证客户端提供的证书链是否可信(在需要客户端证书的情况下)。同样,在代码中,这个方法也被空实现了
到此这篇关于详解Java如何向http/https接口发出请求的文章就介绍到这了,更多相关Java https接口发出请求内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于详解Java如何向http/https接口发出请求的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!