gpt4 book ai didi

java - Android Https 网络服务通信 (SSL/TLS 1.2)

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:43:00 25 4
gpt4 key购买 nike

在我的 Android 应用程序中,我必须与 https 网络服务通信并读取响应。

我已通知服务器使用 TLS 1.2 配置了 SSL

我正在使用以下示例代码连接服务(https get 请求),但只有运行 Android 5.0 或更高版本的设备才能成功通信并读取响应....

该版本(Android 5.0)以下的所有其他设备在尝试建立连接时无法通信并抛出 IOException...

    HttpResponse response = null;
try
{
HttpClient client = new DefaultHttpClient();

HttpGet request = new HttpGet();
request.setURI(new URI("https://domain.co.uk/services/pay.aspx?param1=val1&param2=val2"));

response = client.execute(request);

HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity);
String decodedResStr = URLDecoder.decode(responseString, "UTF-8");

Log.v("AppState", "Response: " + decodedResStr);
}
catch (Exception e)
{
e.printStackTrace();
Log.v("AppState", "Exception: " + e.getMessage() )
}

    // HttpURLConnection urlConnection = null;
HttpsURLConnection urlConnection = null;

try
{
URL url = new URL("https://domain.co.uk/services/pay.aspx?param1=val1&param2=val2");
//urlConnection = (HttpURLConnection) url.openConnection();
urlConnection = (HttpsURLConnection) url.openConnection();

InputStream in = new BufferedInputStream(urlConnection.getInputStream());

}
catch (Exception e)
{
e.printStackTrace();
Log.v("AppState", "Exception: " + e.getMessage() )
}
finally
{
urlConnection.disconnect();
}

问题一

想知道我在这里是否做错了什么(如果我的代码中缺少任何其他参数,这些参数将支持 Android 5.0 之前的旧版本以支持 TLS 1.2 网络服务通信)?

问题二

我刚刚用谷歌搜索并找到了这个 DOCUMENT .

它说 ANDROID 中支持与 TLS 1.2 通信的最低支持浏览器是“GOOGLE Android 5.0 操作系统浏览器”。那么在尝试通过代码(应用程序)连接时是否适用相同的限制?

如果是这样的话,如果要与此网络服务通信(支持 TLS 1.2 网络服务的最低 Android 版本),我应该支持的最低 Android 版本是多少?

示例异常堆栈跟踪如下

Android 2.2 模拟器

    11-06 12:51:01.885: W/System.err(352): java.io.IOException: SSL handshake failure: I/O error during system call, Unknown error: 0
11-06 12:51:01.895: W/System.err(352): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeconnect(Native Method)
11-06 12:51:01.895: W/System.err(352): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:316)
11-06 12:51:01.895: W/System.err(352): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.getSecureSocket(HttpConnection.java:168)
11-06 12:51:01.905: W/System.err(352): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:399)
11-06 12:51:01.915: W/System.err(352): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:1152)
11-06 12:51:01.915: W/System.err(352): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:253)
11-06 12:51:01.915: W/System.err(352): at com.serviceapp.WSHelperHttpURLConnection.executeAndroid(WSHelperHttpURLConnection.java:93)
11-06 12:51:01.915: W/System.err(352): at com.serviceapp.HttpPage$1$1.run(HttpPage.java:69)
11-06 12:51:01.915: W/System.err(352): at java.lang.Thread.run(Thread.java:1096)

Android 3.0 模拟器

11-06 12:56:22.917: W/System.err(447): javax.net.ssl.SSLException: Connection closed by peer
11-06 12:56:22.927: W/System.err(447): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
11-06 12:56:22.927: W/System.err(447): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:485)
11-06 12:56:22.927: W/System.err(447): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:323)
11-06 12:56:22.927: W/System.err(447): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.setupSecureSocket(HttpConnection.java:167)
11-06 12:56:22.937: W/System.err(447): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:479)
11-06 12:56:22.937: W/System.err(447): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeConnection(HttpsURLConnectionImpl.java:428)
11-06 12:56:22.937: W/System.err(447): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.retrieveResponse(HttpURLConnectionImpl.java:1038)
11-06 12:56:22.937: W/System.err(447): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:523)
11-06 12:56:22.937: W/System.err(447): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:283)
11-06 12:56:22.947: W/System.err(447): at com.serviceapp.WSHelperHttpURLConnection.executeAndroid(WSHelperHttpURLConnection.java:93)
11-06 12:56:22.947: W/System.err(447): at com.serviceapp.HttpPage$1$1.run(HttpPage.java:69)
11-06 12:56:22.947: W/System.err(447): at java.lang.Thread.run(Thread.java:1020)

编辑

这是在 Android 4.4.2 和 Android 5.1.1 设备上使用 Robert 的 MySSLSocketFactory 类实现时的完整堆栈跟踪。

11-06 14:26:46.962: W/System.err(14700): java.lang.IllegalArgumentException: protocol TLS1.2 is not supported
11-06 14:26:46.985: W/System.err(14700): at com.android.org.conscrypt.NativeCrypto.checkEnabledProtocols(NativeCrypto.java:879)
11-06 14:26:46.985: W/System.err(14700): at com.android.org.conscrypt.OpenSSLSocketImpl.setEnabledProtocols(OpenSSLSocketImpl.java:807)
11-06 14:26:46.985: W/System.err(14700): at com.serviceapp.MySSLSocketFactory.createSocket(WSURlCon.java:99)
11-06 14:26:46.986: W/System.err(14700): at com.serviceapp.MySSLSocketFactory.createSocket(WSURlCon.java:1)
11-06 14:26:46.986: W/System.err(14700): at com.android.okhttp.Connection.upgradeToTls(Connection.java:131)
11-06 14:26:46.986: W/System.err(14700): at com.android.okhttp.Connection.connect(Connection.java:107)
11-06 14:26:46.986: W/System.err(14700): at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
11-06 14:26:46.987: W/System.err(14700): at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
11-06 14:26:46.988: W/System.err(14700): at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
11-06 14:26:46.988: W/System.err(14700): at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
11-06 14:26:46.990: W/System.err(14700): at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
11-06 14:26:46.990: W/System.err(14700): at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:179)
11-06 14:26:46.991: W/System.err(14700): at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:246)
11-06 14:26:46.991: W/System.err(14700): at com.serviceapp.WSURlCon.executeAndroid(WSURlCon.java:33)
11-06 14:26:46.992: W/System.err(14700): at com.serviceapp.HttpPage$1$1.run(HttpPage.java:74)
11-06 14:26:46.992: W/System.err(14700): at java.lang.Thread.run(Thread.java:848)

最佳答案

根据 Android 开发者文档,TLS 1.2 在 API 级别 20+(Android 4.4 可穿戴设备)的设备上可用并启用:

http://developer.android.com/reference/javax/net/ssl/SSLEngine.html

我假设您的测试设备没有使用该 API 级别,因此您得到的结果是只有 5.0 设备可以连接。

我的个人经验是某些 4.4 设备支持 TLS 1.2,但未启用。您可以尝试通过在使用的 SSLSocket 上调用 setEnabledProtocols(new String[]{"TLSv1.2"}) 来启用它。

一个优雅的解决方案是使用代理模式实现自己的 SSLSocketFactory:

public class MySSLSocketFactory extends SSLSocketFactory {

SSLSocketFactory sslSocketFactory;

public MySSLSocketFactory(SSLSocketFactory sslSocketFactory) {
super();
this.sslSocketFactory = sslSocketFactory;
}

@Override
public String[] getDefaultCipherSuites() {
return sslSocketFactory.getDefaultCipherSuites();
}

@Override
public String[] getSupportedCipherSuites() {
return sslSocketFactory.getSupportedCipherSuites();
}

@Override
public SSLSocket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(s, host, port, autoClose);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}

@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(host, port);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}

@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException,
UnknownHostException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(host, port, localHost, localPort);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}

@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(host, port);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}

@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
throws IOException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(address, port, localAddress, localPort);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}

你可以这样使用它:

    ...
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(new MySSLSocketFactory(urlConnection.getSSLSocketFactory()));
...

关于java - Android Https 网络服务通信 (SSL/TLS 1.2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33567596/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com