2015-04-28 101 views
41

我試圖運行Android中Javax.net.ssl.SSLHandshakeException:javax.net.ssl.SSLProtocolException:SSL握手中止:失敗的SSL庫,通常一個協議錯誤

URLConnection l_connection = null; 
     // Create connection 
     uzip=new UnZipData(mContext); 
     l_url = new URL(serverurl); 

     if ("https".equals(l_url.getProtocol())) { 
      System.out.println("<<<<<<<<<<<<< Before TLS >>>>>>>>>>>>"); 
      sslcontext = SSLContext.getInstance("TLS"); 
      System.out.println("<<<<<<<<<<<<< After TLS >>>>>>>>>>>>"); 
      sslcontext.init(null, 
        new TrustManager[] { new CustomTrustManager()}, 
        new java.security.SecureRandom()); 
      HttpsURLConnection 
        .setDefaultHostnameVerifier(new CustomHostnameVerifier()); 
      HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext 
        .getSocketFactory()); 

      l_connection = (HttpsURLConnection) l_url.openConnection(); 
      ((HttpsURLConnection) l_connection).setRequestMethod("POST"); 
     } else { 
      l_connection = (HttpURLConnection) l_url.openConnection(); 
      ((HttpURLConnection) l_connection).setRequestMethod("POST"); 
     } 
     /*System.setProperty("http.agent", "Android_Phone");*/ 


     l_connection.setConnectTimeout(10000); 
     l_connection.setRequestProperty("Content-Language", "en-US"); 
     l_connection.setUseCaches(false); 
     l_connection.setDoInput(true); 
     l_connection.setDoOutput(true); 
     System.out.println("<<<<<<<<<<<<< Before Connection >>>>>>>>>>>>"); 
     l_connection.connect(); 

在下面的代碼l_connection.connect(),它給這個SSLhandshakeException。有時它可以工作,但大多數情況下它會提供例外。它只發生在Android 4.0仿真器上。我在Android 4.4和5.0上測試它,它工作正常。這可能是什麼原因?請幫助

堆棧跟蹤

04-28 15:51:13.143: W/System.err(2915): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error 
04-28 15:51:13.143: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000) 
04-28 15:51:13.143: W/System.err(2915):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:460) 
04-28 15:51:13.143: W/System.err(2915):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257) 
04-28 15:51:13.143: W/System.err(2915):  at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210) 
04-28 15:51:13.143: W/System.err(2915):  at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477) 
04-28 15:51:13.153: W/System.err(2915):  at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:441) 
04-28 15:51:13.153: W/System.err(2915):  at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282) 
04-28 15:51:13.153: W/System.err(2915):  at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232) 
04-28 15:51:13.153: W/System.err(2915):  at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80) 
04-28 15:51:13.153: W/System.err(2915):  at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164) 
04-28 15:51:13.153: W/System.err(2915):  at com.ofss.fcdb.mobile.android.rms.helpers.NetworkConnector.getConnection(NetworkConnector.java:170) 
04-28 15:51:13.153: W/System.err(2915):  at com.ofss.fcdb.mobile.android.rms.util.InitiateRMS$2.run(InitiateRMS.java:221) 
04-28 15:51:13.153: W/System.err(2915):  at java.lang.Thread.run(Thread.java:856) 
04-28 15:51:13.153: W/System.err(2915): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error 
04-28 15:51:13.153: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000) 
04-28 15:51:13.153: W/System.err(2915):  at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method) 
04-28 15:51:13.153: W/System.err(2915):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410) 
04-28 15:51:13.153: W/System.err(2915):  ... 11 more 
04-28 16:42:44.139: W/ResourceType(3140): No package identifier when getting value for resource number 0x00000000 
+0

做你檢查你的應用程序上真實的設備? –

+0

它是什麼例外?堆棧跟蹤? – EJP

+0

@PareshMayani是的,即使在安裝有Android 4.0的真實設備上,它也會顯示異常。 –

回答

63

我爲它找到解決方案,通過分析使用Wireshark的數據包。我發現的是,在建立安全連接的同時,android從TLSv1回落到SSLv3。這是Android版本< 4.4中的一個錯誤,可以通過從已啓用協議列表中刪除SSLv3協議來解決。我做了一個名爲NoSSLv3SocketFactory.java的自定義socketFactory類。使用它來創建一個socketfactory。

/*Copyright 2015 Bhavit Singh Sengar 
Licensed under the Apache License, Version 2.0 (the "License"); 
you may not use this file except in compliance with the License.You may obtain a copy of the License at 

http://www.apache.org/licenses/LICENSE-2.0 
Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
See the License for the specific language governing permissions and 
limitations under the License.*/ 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.SocketAddress; 
import java.net.SocketException; 
import java.nio.channels.SocketChannel; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
import javax.net.ssl.HandshakeCompletedListener; 
import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.SSLSocket; 
import javax.net.ssl.SSLSocketFactory; 


public class NoSSLv3SocketFactory extends SSLSocketFactory{ 
    private final SSLSocketFactory delegate; 

public NoSSLv3SocketFactory() { 
    this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory(); 
} 

public NoSSLv3SocketFactory(SSLSocketFactory delegate) { 
    this.delegate = delegate; 
} 

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

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

private Socket makeSocketSafe(Socket socket) { 
    if (socket instanceof SSLSocket) { 
     socket = new NoSSLv3SSLSocket((SSLSocket) socket); 
    } 
    return socket; 
} 

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

@Override 
public Socket createSocket(String host, int port) throws IOException { 
    return makeSocketSafe(delegate.createSocket(host, port)); 
} 

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

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

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

private class NoSSLv3SSLSocket extends DelegateSSLSocket { 

    private NoSSLv3SSLSocket(SSLSocket delegate) { 
     super(delegate); 

    } 

    @Override 
    public void setEnabledProtocols(String[] protocols) { 
     if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) { 

      List<String> enabledProtocols = new ArrayList<String>(Arrays.asList(delegate.getEnabledProtocols())); 
      if (enabledProtocols.size() > 1) { 
       enabledProtocols.remove("SSLv3"); 
       System.out.println("Removed SSLv3 from enabled protocols"); 
      } else { 
       System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols)); 
      } 
      protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]); 
     } 

     super.setEnabledProtocols(protocols); 
    } 
} 

public class DelegateSSLSocket extends SSLSocket { 

    protected final SSLSocket delegate; 

    DelegateSSLSocket(SSLSocket delegate) { 
     this.delegate = delegate; 
    } 

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

    @Override 
    public String[] getEnabledCipherSuites() { 
     return delegate.getEnabledCipherSuites(); 
    } 

    @Override 
    public void setEnabledCipherSuites(String[] suites) { 
     delegate.setEnabledCipherSuites(suites); 
    } 

    @Override 
    public String[] getSupportedProtocols() { 
     return delegate.getSupportedProtocols(); 
    } 

    @Override 
    public String[] getEnabledProtocols() { 
     return delegate.getEnabledProtocols(); 
    } 

    @Override 
    public void setEnabledProtocols(String[] protocols) { 
     delegate.setEnabledProtocols(protocols); 
    } 

    @Override 
    public SSLSession getSession() { 
     return delegate.getSession(); 
    } 

    @Override 
    public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { 
     delegate.addHandshakeCompletedListener(listener); 
    } 

    @Override 
    public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { 
     delegate.removeHandshakeCompletedListener(listener); 
    } 

    @Override 
    public void startHandshake() throws IOException { 
     delegate.startHandshake(); 
    } 

    @Override 
    public void setUseClientMode(boolean mode) { 
     delegate.setUseClientMode(mode); 
    } 

    @Override 
    public boolean getUseClientMode() { 
     return delegate.getUseClientMode(); 
    } 

    @Override 
    public void setNeedClientAuth(boolean need) { 
     delegate.setNeedClientAuth(need); 
    } 

    @Override 
    public void setWantClientAuth(boolean want) { 
     delegate.setWantClientAuth(want); 
    } 

    @Override 
    public boolean getNeedClientAuth() { 
     return delegate.getNeedClientAuth(); 
    } 

    @Override 
    public boolean getWantClientAuth() { 
     return delegate.getWantClientAuth(); 
    } 

    @Override 
    public void setEnableSessionCreation(boolean flag) { 
     delegate.setEnableSessionCreation(flag); 
    } 

    @Override 
    public boolean getEnableSessionCreation() { 
     return delegate.getEnableSessionCreation(); 
    } 

    @Override 
    public void bind(SocketAddress localAddr) throws IOException { 
     delegate.bind(localAddr); 
    } 

    @Override 
    public synchronized void close() throws IOException { 
     delegate.close(); 
    } 

    @Override 
    public void connect(SocketAddress remoteAddr) throws IOException { 
     delegate.connect(remoteAddr); 
    } 

    @Override 
    public void connect(SocketAddress remoteAddr, int timeout) throws IOException { 
     delegate.connect(remoteAddr, timeout); 
    } 

    @Override 
    public SocketChannel getChannel() { 
     return delegate.getChannel(); 
    } 

    @Override 
    public InetAddress getInetAddress() { 
     return delegate.getInetAddress(); 
    } 

    @Override 
    public InputStream getInputStream() throws IOException { 
     return delegate.getInputStream(); 
    } 

    @Override 
    public boolean getKeepAlive() throws SocketException { 
     return delegate.getKeepAlive(); 
    } 

    @Override 
    public InetAddress getLocalAddress() { 
     return delegate.getLocalAddress(); 
    } 

    @Override 
    public int getLocalPort() { 
     return delegate.getLocalPort(); 
    } 

    @Override 
    public SocketAddress getLocalSocketAddress() { 
     return delegate.getLocalSocketAddress(); 
    } 

    @Override 
    public boolean getOOBInline() throws SocketException { 
     return delegate.getOOBInline(); 
    } 

    @Override 
    public OutputStream getOutputStream() throws IOException { 
     return delegate.getOutputStream(); 
    } 

    @Override 
    public int getPort() { 
     return delegate.getPort(); 
    } 

    @Override 
    public synchronized int getReceiveBufferSize() throws SocketException { 
     return delegate.getReceiveBufferSize(); 
    } 

    @Override 
    public SocketAddress getRemoteSocketAddress() { 
     return delegate.getRemoteSocketAddress(); 
    } 

    @Override 
    public boolean getReuseAddress() throws SocketException { 
     return delegate.getReuseAddress(); 
    } 

    @Override 
    public synchronized int getSendBufferSize() throws SocketException { 
     return delegate.getSendBufferSize(); 
    } 

    @Override 
    public int getSoLinger() throws SocketException { 
     return delegate.getSoLinger(); 
    } 

    @Override 
    public synchronized int getSoTimeout() throws SocketException { 
     return delegate.getSoTimeout(); 
    } 

    @Override 
    public boolean getTcpNoDelay() throws SocketException { 
     return delegate.getTcpNoDelay(); 
    } 

    @Override 
    public int getTrafficClass() throws SocketException { 
     return delegate.getTrafficClass(); 
    } 

    @Override 
    public boolean isBound() { 
     return delegate.isBound(); 
    } 

    @Override 
    public boolean isClosed() { 
     return delegate.isClosed(); 
    } 

    @Override 
    public boolean isConnected() { 
     return delegate.isConnected(); 
    } 

    @Override 
    public boolean isInputShutdown() { 
     return delegate.isInputShutdown(); 
    } 

    @Override 
    public boolean isOutputShutdown() { 
     return delegate.isOutputShutdown(); 
    } 

    @Override 
    public void sendUrgentData(int value) throws IOException { 
     delegate.sendUrgentData(value); 
    } 

    @Override 
    public void setKeepAlive(boolean keepAlive) throws SocketException { 
     delegate.setKeepAlive(keepAlive); 
    } 

    @Override 
    public void setOOBInline(boolean oobinline) throws SocketException { 
     delegate.setOOBInline(oobinline); 
    } 

    @Override 
    public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { 
     delegate.setPerformancePreferences(connectionTime, latency, bandwidth); 
    } 

    @Override 
    public synchronized void setReceiveBufferSize(int size) throws SocketException { 
     delegate.setReceiveBufferSize(size); 
    } 

    @Override 
    public void setReuseAddress(boolean reuse) throws SocketException { 
     delegate.setReuseAddress(reuse); 
    } 

    @Override 
    public synchronized void setSendBufferSize(int size) throws SocketException { 
     delegate.setSendBufferSize(size); 
    } 

    @Override 
    public void setSoLinger(boolean on, int timeout) throws SocketException { 
     delegate.setSoLinger(on, timeout); 
    } 

    @Override 
    public synchronized void setSoTimeout(int timeout) throws SocketException { 
     delegate.setSoTimeout(timeout); 
    } 

    @Override 
    public void setTcpNoDelay(boolean on) throws SocketException { 
     delegate.setTcpNoDelay(on); 
    } 

    @Override 
    public void setTrafficClass(int value) throws SocketException { 
     delegate.setTrafficClass(value); 
    } 

    @Override 
    public void shutdownInput() throws IOException { 
     delegate.shutdownInput(); 
    } 

    @Override 
    public void shutdownOutput() throws IOException { 
     delegate.shutdownOutput(); 
    } 

    @Override 
    public String toString() { 
     return delegate.toString(); 
    } 

    @Override 
    public boolean equals(Object o) { 
     return delegate.equals(o); 
    } 
} 
} 

使用,而連接這個類是這樣的:

SSLContext sslcontext = SSLContext.getInstance("TLSv1"); 
sslcontext.init(null, null, null); 
SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory()); 

HttpsURLConnection.setDefaultSSLSocketFactory(NoSSLv3Factory); 
l_connection = (HttpsURLConnection) l_url.openConnection(); 
l_connection.connect(); 

UPDATE:

現在,正確的解決辦法是使用Google Play Services安裝更新的安全提供:

ProviderInstaller.installIfNeeded(getApplicationContext()); 

This effectivel y使您的應用能夠訪問較新版本的OpenSSL和Java安全提供程序,其中包括對SSLEngine中的TLSv1.2的支持。一旦安裝了新的供應商,您可以創建支持的SSLv3,使用TLSv1,TLSv1.1和TLSv1.2工作的通常方式的SSLEngine:

SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); 
    sslContext.init(null, null, null); 
    SSLEngine engine = sslContext.createSSLEngine(); 

,也可以使用engine.setEnabledProtocols限制啓用的協議。

不要忘了添加以下的依賴(latest version found here):

compile 'com.google.android.gms:play-services-auth:11.8.0' 

欲瞭解更多信息,結賬這個link

+13

如果我在棒棒糖設備上發生此錯誤,該怎麼辦? –

+1

真的很棒...它適用於Android 4.3 –

+1

適用於Android API級別22,很好的工作! –

1

只有當我在genymotion上使用代理(< 4.4)時,它才能被重複使用。

檢查 設置 - >無線&網絡 - >無線網絡的代理設置 - >(長按WiredSSID) - >修改網絡

選擇顯示高級選項: 代理設置爲NONE。

61

方案

我正上運行Android的版本比Android 5.0的早期設備SSLHandshake例外。在我的使用案例中,我也想創建一個TrustManager來信任我的客戶端證書。

我實現了NoSSLv3SocketFactoryNoSSLv3Factory從我的客戶端支持的協議列表中刪除SSLv3,但我沒有得到任何這些解決方案的工作。

有些事情我瞭解到:

  • 在設備上年齡比的是Android 5.0 TLSv1.1和TLSv1.2工作協議不是默認啓用的。
  • 默認情況下,SSLv3協議在Android 5.0之前的設備上未被禁用。
  • SSLv3 is not a secure協議,因此需要在建立連接之前將其從客戶端支持的協議列表中刪除。

什麼工作對我來說

允許Android的安全Provider來開始你的應用程序時更新。

5.0+之前的默認提供程序不會禁用SSLv3。如果您可以訪問Google Play服務,則從您的應用修補Android的安全提供程序相對比較簡單。

private void updateAndroidSecurityProvider(Activity callingActivity) { 
    try { 
     ProviderInstaller.installIfNeeded(this); 
    } catch (GooglePlayServicesRepairableException e) { 
     // Thrown when Google Play Services is not installed, up-to-date, or enabled 
     // Show dialog to allow users to install, update, or otherwise enable Google Play services. 
     GooglePlayServicesUtil.getErrorDialog(e.getConnectionStatusCode(), callingActivity, 0); 
    } catch (GooglePlayServicesNotAvailableException e) { 
     Log.e("SecurityException", "Google Play Services not available."); 
    } 
} 

如果你現在創建OkHttpClient或HttpURLConnection的TLSv1.1和TLSv1.2工作應該作爲協議和SSLv3的應該被刪除。如果在調用ProviderInstaller.installIfNeeded(...)之前初始化客戶端/連接(或者更具體地說它是SSLContext),那麼它將需要被重新創建。

不要忘了添加以下的依賴(latest version found here):

compile 'com.google.android.gms:play-services-auth:11.8.0' 

來源:

除了

我並不需要明確設置其密碼算法我的客戶應該使用,但我發現了一個SO發佈推薦那些被認爲是最安全的,在寫作的時候: NoSSLv3SocketFactory:Which Cipher Suites to enable for SSL Socket?

+1

感謝隊友,你剛剛幫助了一位朋友! :) – ticofab

+0

這需要更多upvotes。謝謝一堆 – tmho

+0

在我的情況下工作 –

0

我這個解決的問題。 java的

import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.SocketAddress; 
import java.net.SocketException; 
import java.nio.channels.SocketChannel; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
import javax.net.ssl.HandshakeCompletedListener; 
import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.SSLSocket; 
import javax.net.ssl.SSLSocketFactory; 

public class NoSSLv3SocketFactory extends SSLSocketFactory { 
    private final SSLSocketFactory delegate; 

    public NoSSLv3SocketFactory() { 
     this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory(); 
    } 

    public NoSSLv3SocketFactory(SSLSocketFactory delegate) { 
     this.delegate = delegate; 
    } 

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

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

    private Socket makeSocketSafe(Socket socket) { 
     if (socket instanceof SSLSocket) { 
      socket = new NoSSLv3SSLSocket((SSLSocket) socket); 
     } 
     return socket; 
    } 

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

    @Override 
    public Socket createSocket(String host, int port) throws IOException { 
     return makeSocketSafe(delegate.createSocket(host, port)); 
    } 

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

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

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

    private class NoSSLv3SSLSocket extends DelegateSSLSocket { 

     private NoSSLv3SSLSocket(SSLSocket delegate) { 
      super(delegate); 

     } 

     @Override 
     public void setEnabledProtocols(String[] protocols) { 
      if (protocols != null && protocols.length == 1 
        && "SSLv3".equals(protocols[0])) { 

       List<String> enabledProtocols = new ArrayList<String>(
         Arrays.asList(delegate.getEnabledProtocols())); 
       if (enabledProtocols.size() > 1) { 
        enabledProtocols.remove("SSLv3"); 
        System.out.println("Removed SSLv3 from enabled protocols"); 
       } else { 
        System.out.println("SSL stuck with protocol available for " 
          + String.valueOf(enabledProtocols)); 
       } 
       protocols = enabledProtocols 
         .toArray(new String[enabledProtocols.size()]); 
      } 

//   super.setEnabledProtocols(protocols); 
      super.setEnabledProtocols(new String[]{"TLSv1.2"}); 
     } 
    } 

    public class DelegateSSLSocket extends SSLSocket { 

     protected final SSLSocket delegate; 

     DelegateSSLSocket(SSLSocket delegate) { 
      this.delegate = delegate; 
     } 

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

     @Override 
     public String[] getEnabledCipherSuites() { 
      return delegate.getEnabledCipherSuites(); 
     } 

     @Override 
     public void setEnabledCipherSuites(String[] suites) { 
      delegate.setEnabledCipherSuites(suites); 
     } 

     @Override 
     public String[] getSupportedProtocols() { 
      return delegate.getSupportedProtocols(); 
     } 

     @Override 
     public String[] getEnabledProtocols() { 
      return delegate.getEnabledProtocols(); 
     } 

     @Override 
     public void setEnabledProtocols(String[] protocols) { 
      delegate.setEnabledProtocols(protocols); 
     } 

     @Override 
     public SSLSession getSession() { 
      return delegate.getSession(); 
     } 

     @Override 
     public void addHandshakeCompletedListener(
       HandshakeCompletedListener listener) { 
      delegate.addHandshakeCompletedListener(listener); 
     } 

     @Override 
     public void removeHandshakeCompletedListener(
       HandshakeCompletedListener listener) { 
      delegate.removeHandshakeCompletedListener(listener); 
     } 

     @Override 
     public void startHandshake() throws IOException { 
      delegate.startHandshake(); 
     } 

     @Override 
     public void setUseClientMode(boolean mode) { 
      delegate.setUseClientMode(mode); 
     } 

     @Override 
     public boolean getUseClientMode() { 
      return delegate.getUseClientMode(); 
     } 

     @Override 
     public void setNeedClientAuth(boolean need) { 
      delegate.setNeedClientAuth(need); 
     } 

     @Override 
     public void setWantClientAuth(boolean want) { 
      delegate.setWantClientAuth(want); 
     } 

     @Override 
     public boolean getNeedClientAuth() { 
      return delegate.getNeedClientAuth(); 
     } 

     @Override 
     public boolean getWantClientAuth() { 
      return delegate.getWantClientAuth(); 
     } 

     @Override 
     public void setEnableSessionCreation(boolean flag) { 
      delegate.setEnableSessionCreation(flag); 
     } 

     @Override 
     public boolean getEnableSessionCreation() { 
      return delegate.getEnableSessionCreation(); 
     } 

     @Override 
     public void bind(SocketAddress localAddr) throws IOException { 
      delegate.bind(localAddr); 
     } 

     @Override 
     public synchronized void close() throws IOException { 
      delegate.close(); 
     } 

     @Override 
     public void connect(SocketAddress remoteAddr) throws IOException { 
      delegate.connect(remoteAddr); 
     } 

     @Override 
     public void connect(SocketAddress remoteAddr, int timeout) 
       throws IOException { 
      delegate.connect(remoteAddr, timeout); 
     } 

     @Override 
     public SocketChannel getChannel() { 
      return delegate.getChannel(); 
     } 

     @Override 
     public InetAddress getInetAddress() { 
      return delegate.getInetAddress(); 
     } 

     @Override 
     public InputStream getInputStream() throws IOException { 
      return delegate.getInputStream(); 
     } 

     @Override 
     public boolean getKeepAlive() throws SocketException { 
      return delegate.getKeepAlive(); 
     } 

     @Override 
     public InetAddress getLocalAddress() { 
      return delegate.getLocalAddress(); 
     } 

     @Override 
     public int getLocalPort() { 
      return delegate.getLocalPort(); 
     } 

     @Override 
     public SocketAddress getLocalSocketAddress() { 
      return delegate.getLocalSocketAddress(); 
     } 

     @Override 
     public boolean getOOBInline() throws SocketException { 
      return delegate.getOOBInline(); 
     } 

     @Override 
     public OutputStream getOutputStream() throws IOException { 
      return delegate.getOutputStream(); 
     } 

     @Override 
     public int getPort() { 
      return delegate.getPort(); 
     } 

     @Override 
     public synchronized int getReceiveBufferSize() throws SocketException { 
      return delegate.getReceiveBufferSize(); 
     } 

     @Override 
     public SocketAddress getRemoteSocketAddress() { 
      return delegate.getRemoteSocketAddress(); 
     } 

     @Override 
     public boolean getReuseAddress() throws SocketException { 
      return delegate.getReuseAddress(); 
     } 

     @Override 
     public synchronized int getSendBufferSize() throws SocketException { 
      return delegate.getSendBufferSize(); 
     } 

     @Override 
     public int getSoLinger() throws SocketException { 
      return delegate.getSoLinger(); 
     } 

     @Override 
     public synchronized int getSoTimeout() throws SocketException { 
      return delegate.getSoTimeout(); 
     } 

     @Override 
     public boolean getTcpNoDelay() throws SocketException { 
      return delegate.getTcpNoDelay(); 
     } 

     @Override 
     public int getTrafficClass() throws SocketException { 
      return delegate.getTrafficClass(); 
     } 

     @Override 
     public boolean isBound() { 
      return delegate.isBound(); 
     } 

     @Override 
     public boolean isClosed() { 
      return delegate.isClosed(); 
     } 

     @Override 
     public boolean isConnected() { 
      return delegate.isConnected(); 
     } 

     @Override 
     public boolean isInputShutdown() { 
      return delegate.isInputShutdown(); 
     } 

     @Override 
     public boolean isOutputShutdown() { 
      return delegate.isOutputShutdown(); 
     } 

     @Override 
     public void sendUrgentData(int value) throws IOException { 
      delegate.sendUrgentData(value); 
     } 

     @Override 
     public void setKeepAlive(boolean keepAlive) throws SocketException { 
      delegate.setKeepAlive(keepAlive); 
     } 

     @Override 
     public void setOOBInline(boolean oobinline) throws SocketException { 
      delegate.setOOBInline(oobinline); 
     } 

     @Override 
     public void setPerformancePreferences(int connectionTime, int latency, 
       int bandwidth) { 
      delegate.setPerformancePreferences(connectionTime, latency, 
        bandwidth); 
     } 

     @Override 
     public synchronized void setReceiveBufferSize(int size) 
       throws SocketException { 
      delegate.setReceiveBufferSize(size); 
     } 

     @Override 
     public void setReuseAddress(boolean reuse) throws SocketException { 
      delegate.setReuseAddress(reuse); 
     } 

     @Override 
     public synchronized void setSendBufferSize(int size) 
       throws SocketException { 
      delegate.setSendBufferSize(size); 
     } 

     @Override 
     public void setSoLinger(boolean on, int timeout) throws SocketException { 
      delegate.setSoLinger(on, timeout); 
     } 

     @Override 
     public synchronized void setSoTimeout(int timeout) 
       throws SocketException { 
      delegate.setSoTimeout(timeout); 
     } 

     @Override 
     public void setTcpNoDelay(boolean on) throws SocketException { 
      delegate.setTcpNoDelay(on); 
     } 

     @Override 
     public void setTrafficClass(int value) throws SocketException { 
      delegate.setTrafficClass(value); 
     } 

     @Override 
     public void shutdownInput() throws IOException { 
      delegate.shutdownInput(); 
     } 

     @Override 
     public void shutdownOutput() throws IOException { 
      delegate.shutdownOutput(); 
     } 

     @Override 
     public String toString() { 
      return delegate.toString(); 
     } 

     @Override 
     public boolean equals(Object o) { 
      return delegate.equals(o); 
     } 
    } 
} 

主要類:

URL url = new URL("https://www.example.com/test.png"); 
URLConnection l_connection = null; 
SSLContext sslcontext = SSLContext.getInstance("TLSv1.2"); 
sslcontext.init(null, null, null); 
SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory()); 
0

這解決了這個問題對我來說:

The Android documentation for SSLSocket says that TLS 1.1 and TLS 1.2 is supported within android starting API level 16+ (Android 4.1, Jelly Bean). But it is by default disabled but starting with API level 20+ (Android 4.4 for watch, Kitkat Watch and Android 5.0 for phone, Lollipop) they are enabled. But it is very hard to find any documentation about how to enable it for phones running 4.1 for example. To enable TLS 1.1 and 1.2 you need to create a custom SSLSocketFactory that is going to proxy all calls to a default SSLSocketFactory implementation. In addition to that do we have to override all createSocket methods and callsetEnabledProtocols on the returned SSLSocket to enable TLS 1.1 and TLS 1.2. For an example implementation just follow the link below.

android 4.1. enable tls1.1 and tls 1.2