java HttpsURLConnection请求报错

本文记录了一次从使用HttpClient转向Java API URLConnection过程中遇到的HTTPS连接问题。主要错误为服务器返回未知协议,经排查发现为服务器未配置HTTPS所致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

09-19 17:04:58.184: W/System.err(15254): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6494b678: Failure in SSL library, usually a protocol error
09-19 17:04:58.184: W/System.err(15254): error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:769 0x5d875dbc:0x00000000)
09-19 17:04:58.184: W/System.err(15254): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:448)
09-19 17:04:58.184: W/System.err(15254): at com.android.okhttp.Connection.upgradeToTls(Connection.java:146)
09-19 17:04:58.184: W/System.err(15254): at com.android.okhttp.Connection.connect(Connection.java:107)
09-19 17:04:58.184: W/System.err(15254): at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
09-19 17:04:58.184: W/System.err(15254): at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
09-19 17:04:58.184: W/System.err(15254): at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
09-19 17:04:58.184: W/System.err(15254): at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
09-19 17:04:58.184: W/System.err(15254): at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:89)
09-19 17:04:58.184: W/System.err(15254): at com.android.okhttp.internal.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:197)
09-19 17:04:58.184: W/System.err(15254): at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:254)
09-19 17:04:58.184: W/System.err(15254): at com.rtm.common.http.RMHttpUtil.postHttpsConnection(RMHttpUtil.java:258)
09-19 17:04:58.184: W/System.err(15254): at com.rtm.location.utils.RMUserUtil$UserCall.onCallBackStart(RMUserUtil.java:69)
09-19 17:04:58.184: W/System.err(15254): at com.rtm.common.utils.RMAsyncTask.doInBackground(RMAsyncTask.java:24)
09-19 17:04:58.224: W/System.err(15254): at android.os.AsyncTask$2.call(AsyncTask.java:288)
09-19 17:04:58.244: W/System.err(15254): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
09-19 17:04:58.244: W/System.err(15254): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
09-19 17:04:58.244: W/System.err(15254): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
09-19 17:04:58.244: W/System.err(15254): at java.lang.Thread.run(Thread.java:841)
09-19 17:04:58.244: W/System.err(15254): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6494b678: Failure in SSL library, usually a protocol error
09-19 17:04:58.244: W/System.err(15254): error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:769 0x5d875dbc:0x00000000)
09-19 17:04:58.244: W/System.err(15254): at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
09-19 17:04:58.244: W/System.err(15254): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:406)

09-19 17:04:58.244: W/System.err(15254): ... 17 more



之前一直用HttpClient写http和https,自从安卓不建议使用后,自己改用java api UrlConnection,结果使用中报错,蓝色部分是java api指定SSL官方报错,此种报错可以看做一个大类,所以要看细节报错,红色部分研究过SSL加密验证的都知道这个是说:得到服务器告知结果:未知协议,说明服务器不能识别https,后来发现我们服务器还没有部署https,是我太着急了。谨记,后续遇到在扩展

<think>嗯,用户问的是如何使用HttpsURLConnection实现HTTPS通讯。首先,我需要回忆一下Java中处理HTTPS请求的基本流程。HttpsURLConnectionJava标准库中的一个类,用于处理HTTPS请求,但和HTTP不同,HTTPS需要处理SSL/TLS证书相关的验证。 首先,可能需要先创建一个URL对象,然后打开连接,转换成HttpsURLConnection。然后设置请求方法,比如GET或POST,接着处理输入输出流。不过HTTPS涉及到证书的问题,用户可能需要了解如何处理自签名证书或者绕过证书验证,这在开发测试阶段比较常见,但生产环境不建议这么做。 然后,用户可能不知道如何信任所有证书,这时候需要设置一个信任所有证书的TrustManager。不过需要注意这样做不安全,只能用于测试。具体步骤可能是创建SSLContext,使用自定义的TrustManager,然后设置到HttpsURLConnection中。 另外,客户端证书的情况可能也需要考虑,但用户没有提到,可能暂时不需要。还要处理主机名验证的问题,默认情况下会验证主机名是否与证书匹配,如果不匹配会报错,这时候可能需要自定义HostnameVerifier,比如接受所有主机名,同样不安全但测试用。 然后,代码示例的大致步骤应该是:创建URL对象,打开连接,设置请求方法,设置HostnameVerifier和SSLSocketFactory,处理响应流。同时,异常处理也很重要,比如SSLHandshakeException,可能由证书问题引起。 可能需要分两种情况,一种是默认的信任所有证书(不推荐),另一种是配置信任特定证书。用户可能更关注前者,因为后者需要导入证书等步骤更复杂。还要提醒用户生产环境中应该使用正确的证书配置,而不是绕过验证。 另外,Java 8和更新的版本可能会有不同的行为吗?比如默认启用的TLS版本,可能需要显式设置。还有,如何处理POST请求,设置请求头,比如Content-Type,处理输出流等,可能需要补充。 总结回答的结构:先介绍HttpsURLConnection的基本用法,然后说明如何处理证书验证和主机名验证,提供示例代码,并强调安全注意事项。可能还需要提到SSLContext的初始化和自定义TrustManager的实现。</think>以下是使用`HttpsURLConnection`实现HTTPS通讯的详细步骤和注意事项: --- ### 一、基本流程 ```java import javax.net.ssl.HttpsURLConnection; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; public class HttpsExample { public static void main(String[] args) throws Exception { // 1. 创建URL对象 URL url = new URL("https://example.com"); // 2. 打开HTTPS连接 HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); // 3. 设置请求方法 conn.setRequestMethod("GET"); // 4. 处理响应 try (BufferedReader reader = new BufferedReader( new InputStreamReader(conn.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } } } ``` --- ### 二、处理SSL证书验证 #### 场景1:信任所有证书(仅测试环境使用) ```java import javax.net.ssl.*; public class TrustAllCertificates { public static void disableCertificateValidation() throws Exception { // 创建信任所有证书的TrustManager TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { } } }; // 初始化SSLContext SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // 禁用主机名验证 HttpsURLConnection.setDefaultHostnameVerifier( (hostname, session) -> true); } } ``` #### 使用方式 ```java public static void main(String[] args) throws Exception { TrustAllCertificates.disableCertificateValidation(); // 先禁用证书验证 // 后续执行常规HTTPS请求... } ``` #### 场景2:信任特定证书(生产推荐) 需将证书导入Java信任库: ```bash keytool -import -alias example -keystore cacerts -file server.cer ``` --- ### 三、完整示例(包含POST请求) ```java import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.URL; import java.nio.charset.StandardCharsets; public class HttpsPostExample { public static void main(String[] args) throws Exception { URL url = new URL("https://example.com/api"); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); // 设置请求属性 conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/json"); conn.setDoOutput(true); // 发送请求体 String jsonBody = "{\"key\":\"value\"}"; try (OutputStream os = conn.getOutputStream()) { os.write(jsonBody.getBytes(StandardCharsets.UTF_8)); } // 处理响应 try (BufferedReader br = new BufferedReader( new InputStreamReader(conn.getInputStream()))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } } } ``` --- ### 四、关键注意事项 1. **证书安全** - 生产环境必须使用有效证书,避免关闭证书验证 - 自签名证书需通过`keytool`导入JVM信任库 2. **协议配置** ```java // 强制使用TLSv1.2(针对老旧系统) System.setProperty("https.protocols", "TLSv1.2"); ``` 3. **超时设置** ```java conn.setConnectTimeout(5000); // 5秒连接超时 conn.setReadTimeout(10000); // 10秒读取超时 ``` 4. **异常处理** - 捕获`SSLHandshakeException`处理证书错误 - 处理`IOException`应对网络问题 --- ### 五、最佳实践建议 - 使用Apache HttpClient或OkHttp等成熟库代替原生实现 - 定期更新JRE中的根证书 - 通过`SSLContext`自定义安全策略时,优先选择更安全的密码套件 > 通过合理配置,`HttpsURLConnection`能够满足基本HTTPS通讯需求,但在复杂场景下建议使用专业HTTP客户端库。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值