【问题标题】:Android 7.0 : 'javax.net.ssl.SSLHandshakeException: Connection closed by peerAndroid 7.0:'javax.net.ssl.SSLHandshakeException:连接被对等方关闭
【发布时间】:2017-09-22 20:26:00
【问题描述】:

当我尝试从我的应用程序访问“https”网络服务时,它会给出“javax.net.ssl.SSLHandshakeException: Connection closed by peer”错误。相同的 Web Service 在 Chrome 浏览器中运行良好。

此问题仅在 Android 7.0 上发生,它在 Android 6.0 和 5.0 中运行良好。

服务器是 CA 认证的,不是自签名的。

【问题讨论】:

标签: android https ssl-certificate sslhandshakeexception httpsurlconnection


【解决方案1】:

尝试使用此代码,它对我有用:

 private static void initializeSSLContext(Context mContext){
    try {
        SSLContext.getInstance("TLSv1.2");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    try {
        ProviderInstaller.installIfNeeded(mContext.getApplicationContext());
    } catch (GooglePlayServicesRepairableException e) {
        e.printStackTrace();
    } catch (GooglePlayServicesNotAvailableException e) {
        e.printStackTrace();
    }
}

别忘了使用 usr google 安全库:

  compile 'com.google.android.gms:play-services-safetynet:11.6.2'

【讨论】:

  • 您可以在应用程序类的 onCreate 中添加它,也可以在调用您的服务之前添加它
  • 知道如何将此代码添加到 Cordova/Ionic 应用程序吗?
  • 对不起,我不知道,我之前没有在 Ionic 中编程,但是如果你可以创建一个函数,那么在服务调用之前添加函数的调用(当你调用 api 来连接服务器时) )
【解决方案2】:

为了解决这个问题,我不得不使用扩展的 SSLSocket 类来包含所有协议和密码套件。解决方案在于 GetProtocolList() & GetCipherList()

private static OkHttpClient.Builder enableAllProtocols(OkHttpClient.Builder client) {
    try {
        client.sslSocketFactory(new SSLSocketFactoryExtended(), provideX509TrustManager());
    } catch (Exception exc) {
        Log.e("OkHttpTLSCompat", "Error while setting Protocols", exc);
    }
    return client;
}

SSLSocketFactory扩展类文件

public class SSLSocketFactoryExtended extends SSLSocketFactory {
    private SSLContext mSSLContext;
    private String[] mCiphers;
    private String[] mProtocols;

    public SSLSocketFactoryExtended() throws NoSuchAlgorithmException, KeyManagementException {
        initSSLSocketFactoryEx(null,null,null);
    }

    public String[] getDefaultCipherSuites() {
        return mCiphers;
    }

    public String[] getSupportedCipherSuites() {
        return mCiphers;
    }

    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(s, host, port, autoClose);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(address, port, localAddress, localPort);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(host, port, localHost, localPort);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(host, port);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException {
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        SSLSocket ss = (SSLSocket)factory.createSocket(host, port);

        ss.setEnabledProtocols(mProtocols);
        ss.setEnabledCipherSuites(mCiphers);

        return ss;
    }

    private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException {
        mSSLContext = SSLContext.getInstance("TLS");
        mSSLContext.init(km, tm, random);

        mProtocols = GetProtocolList();
        mCiphers = GetCipherList();
    }

    protected String[] GetProtocolList() {
        String[] protocols = { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
        String[] availableProtocols = null;

        SSLSocket socket = null;

        try {
            SSLSocketFactory factory = mSSLContext.getSocketFactory();
            socket = (SSLSocket)factory.createSocket();

            availableProtocols = socket.getSupportedProtocols();
        } catch(Exception e) {
            return new String[]{ "TLSv1" };
        } finally {
            if(socket != null)
                try {
                    socket.close();
                } catch (IOException e) {
                }
        }

        List<String> resultList = new ArrayList<String>();
        for(int i = 0; i < protocols.length; i++) {
            int idx = Arrays.binarySearch(availableProtocols, protocols[i]);
            if(idx >= 0)
                resultList.add(protocols[i]);
        }

        return resultList.toArray(new String[0]);
    }

    protected String[] GetCipherList() {
        List<String> resultList = new ArrayList<String>();
        SSLSocketFactory factory = mSSLContext.getSocketFactory();
        for(String s : factory.getSupportedCipherSuites()){
            resultList.add(s);
        }
        return resultList.toArray(new String[resultList.size()]);
    }
}

【讨论】:

  • 这段代码效果很好。该服务器是旧的 WIndows 2003 服务器。不支持 TLS 1.2
  • 对了,这个怎么用?
猜你喜欢
  • 1970-01-01
  • 2018-07-31
  • 1970-01-01
  • 1970-01-01
  • 2016-08-28
  • 1970-01-01
  • 2017-12-03
  • 2020-02-03
  • 2017-09-20
相关资源
最近更新 更多