2015-03-25 74 views
11

启用TLSv1.2工作我用OKHttp我的项目。我想为我的服务呼叫启用TLSv1.2。任何机构都可以告诉我如何启用它。的Android在OKHttp

+0

它是如何为你工作? 请告诉我我不能问的问题stackoverflow – 2015-11-26 23:39:12

+0

这个解决方案解决了我的问题:https://stackoverflow.com/a/45853669/3448003 – 2017-08-24 07:15:12

回答

5

据我所知OKHttp不包括自己的SSL/TLS库,因此它只是使用由Android提供的标准的SSLSocket。

什么都支持TLS版本(和启用)取决于所使用的Android版本。 在某些电话上支持TLS 1.2,但默认情况下未启用。在这种情况下,您可以通过实现自定义包装器SSLSocketFactory来启用它,该包装器在内部使用默认的SSLSocketFactory,并在创建的每个套接字上调用setEnabledProtocols(new String{"TLS1.2"})

6

见OkHttp的HTTPS documentation

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) 
    .tlsVersions(TlsVersion.TLS_1_2) 
    .cipherSuites( 
    CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 
    CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 
    CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) 
    .build(); 
OkHttpClient client = ... 
client.setConnectionSpecs(Collections.singletonList(spec)); 
+2

作为文档说 - 这只会在Android 5.0或更高版本 – Shlomi 2015-04-21 08:08:30

+0

它doesn甚至不适用于Android 5.0。我得到SSL HandshakeException。 – 2015-10-22 20:53:09

+0

这不起作用 – 2015-11-26 23:34:52

0

这是基本相同的答案above,但我觉得自己像一个代码示例将是谁比谁这里的土地和不加快速度航行的java的SSL景观有用。

什么最终结束了我的工作是基于此报告的问题:https://github.com/mattleibow/square-bindings/issues/1
从这个要点https://gist.github.com/mattleibow/c8abfa323db094b820cc

注意这些代码示例是用C#/ Xamarin但也很容易被转换为Java。

internal class CompleteSSLSocketFactory : SSLSocketFactory 
{ 
    private readonly SSLSocketFactory innerFactory; 

    public CompleteSSLSocketFactory (SSLSocketFactory innerFactory) 
    { 
     this.innerFactory = innerFactory; 
    } 

    public override string[] GetDefaultCipherSuites() 
    { 
     return innerFactory.GetDefaultCipherSuites(); 
    } 

    public override string[] GetSupportedCipherSuites() 
    { 
     return innerFactory.GetSupportedCipherSuites(); 
    } 

    public override Socket CreateSocket() 
    { 
     return MakeSocketSafe (innerFactory.CreateSocket()); 
    } 

    public override Socket CreateSocket (Socket s, string host, int port, bool autoClose) 
    { 
     return MakeSocketSafe (innerFactory.CreateSocket (s, host, port, autoClose)); 
    } 

    public override Socket CreateSocket (string host, int port) 
    { 
     return MakeSocketSafe (innerFactory.CreateSocket (host, port)); 
    } 

    public override Socket CreateSocket (string host, int port, InetAddress localHost, int localPort) 
    { 
     return MakeSocketSafe (innerFactory.CreateSocket (host, port, localHost, localPort)); 
    } 

    public override Socket CreateSocket (InetAddress host, int port) 
    { 
     return MakeSocketSafe (innerFactory.CreateSocket (host, port)); 
    } 

    public override Socket CreateSocket (InetAddress address, int port, InetAddress localAddress, int localPort) 
    { 
     return MakeSocketSafe (innerFactory.CreateSocket (address, port, localAddress, localPort)); 
    } 

    private Socket MakeSocketSafe (Socket socket) 
    { 
     var sslSocket = socket as SSLSocket; 
     if (sslSocket != null) { 
      // enable all supported protocols for this socket 
      sslSocket.SetEnabledProtocols (sslSocket.GetSupportedProtocols()); 
      sslSocket.SetEnabledCipherSuites (sslSocket.GetSupportedCipherSuites()); 
     } 
     return socket; 
    } 
} 

,然后调用它像:

// this.client is an OkHttpClient 
if (Android.OS.Build.VERSION.SdkInt < BuildVersionCodes.Lollipop) { 
    this.client.SetSslSocketFactory(new CompleteSSLSocketFactory(HttpsURLConnection.DefaultSSLSocketFactory)); 
} 

这为我工作,在API测试19

1

原来我的解决方案是非常相似的Ken的(除Java之外)。我发现它here虽然不得不作出一些小的改变,使其工作。希望这个作品'开箱即用'为他人。

public class TLSSocketFactoryCompat extends SSLSocketFactory { 

private SSLSocketFactory internalSSLSocketFactory; 

public TLSSocketFactoryCompat() throws KeyManagementException, NoSuchAlgorithmException { 
    SSLContext context = SSLContext.getInstance("TLS"); 
    context.init(null, null, null); 
    internalSSLSocketFactory = context.getSocketFactory(); 
} 

public TLSSocketFactoryCompat(TrustManager[] tm) throws KeyManagementException, NoSuchAlgorithmException { 
    SSLContext context = SSLContext.getInstance("TLS"); 
    context.init(null, tm, new java.security.SecureRandom()); 
    internalSSLSocketFactory = context.getSocketFactory(); 
} 

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

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

@Override 
public Socket createSocket() throws IOException { 
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket()); 
} 

@Override 
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { 
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); 
} 

@Override 
public Socket createSocket(String host, int port) throws IOException, UnknownHostException { 
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); 
} 

@Override 
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { 
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)); 
} 

@Override 
public Socket createSocket(InetAddress host, int port) throws IOException { 
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); 
} 

@Override 
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { 
    return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); 
} 

private Socket enableTLSOnSocket(Socket socket) { 
    if(socket != null && (socket instanceof SSLSocket)) { 
     //Create list of supported protocols 
     ArrayList<String> supportedProtocols = new ArrayList<>(); 
     for (String protocol : ((SSLSocket)socket).getEnabledProtocols()) { 

      //Log.d("TLSSocketFactory", "Supported protocol:" + protocol); 
      //Only add TLS protocols (don't want ot support older SSL versions) 
      if (protocol.toUpperCase().contains("TLS")) { 
       supportedProtocols.add(protocol); 
      } 
     } 
     //Force add TLSv1.1 and 1.2 if not already added 
     if (!supportedProtocols.contains("TLSv1.1")) { 
      supportedProtocols.add("TLSv1.1"); 
     } 
     if (!supportedProtocols.contains("TLSv1.2")) { 
      supportedProtocols.add("TLSv1.2"); 
     } 

     String[] protocolArray = supportedProtocols.toArray(new String[supportedProtocols.size()]); 
     /*for (int i = 0; i < protocolArray.length; i++) { 
      Log.d("TLSSocketFactory", "protocolArray[" + i + "]" + protocolArray[i]); 
     }*/ 

     //enable protocols in our list 
     ((SSLSocket)socket).setEnabledProtocols(protocolArray); 
    } 
    return socket; 
} 

}

用法:

OkHttpClient httpClient = new OkHttpClient(); 
    //Add Custom SSL Socket Factory which adds TLS 1.1 and 1.2 support for Android 4.1-4.4 
    try { 
     httpClient.setSslSocketFactory(new TLSSocketFactoryCompat()); 
    } catch (KeyManagementException e) { 
     e.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 
+0

我对此有很高的期望,但是我看到'启用TLS 1.2 启用TLS 1.2 启用TLS 1.2 启用TLS 1.2 启用TLS 1.2 启用TLS 1.2 启用TLS 1.2 启用TLS 1.2 javax.net.ssl.SSLHandshakeException:javax.net.ssl.SSLProtocolException:SSL握手终止:SSL = 0x5ff7f518:失败在SSL库,通常一个协议错误 错误:14094410:SSL例程:SSL3_READ_BYTES:sslv3警报握手失败(external/openssl/ssl/s3_pkt.c:1256 0x5fe90e28:0x00000003) at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshak e(OpenSSLSocketImpl.java:568)' – 2016-07-11 10:43:06

+0

至少它在放弃之前尝试enableTLSOnSocket()8次,在几秒钟的时间内。 – 2016-07-11 10:43:47

+0

有人在某个地方,我不确定你得到的错误实际上是相关的(可能是一个证书问题),但它提醒我,我更新了这个类,以确保只添加了支持的协议列表。我想在它可能只剩下TLS 1.1和1.2启用之前。希望这有助于。 – aaronmarino 2016-07-11 16:09:17

2

检查我的代码!工作完美!

private void checkTls() { 
    if (android.os.Build.VERSION.SDK_INT < 21) { 
     try { 
      ProviderInstaller.installIfNeededAsync(this, new ProviderInstaller.ProviderInstallListener() { 
       @Override 
       public void onProviderInstalled() { 
       } 

       @Override 
       public void onProviderInstallFailed(int i, Intent intent) { 
       } 
      }); 
     } catch (Exception e) { 
      finish(); 
      e.printStackTrace(); 
     } 
    } 
} 
+0

在调用Web服务之前使用它。只需要在您的应用程序中调用一次 – 2016-08-15 20:50:33

+0

此解决方案不适用于所有人。 ProviderInstaller类来自Google Play服务,并且Google Play服务在每个Android设备上都不可用。尤其在中国,GPS不允许使用。 – EJK 2016-11-23 20:11:07