Android 7.0:"javax.net.ssl.SSLHandshakeException:连接已被同级关闭 [英] Android 7.0 : 'javax.net.ssl.SSLHandshakeException: Connection closed by peer

查看:154
本文介绍了Android 7.0:"javax.net.ssl.SSLHandshakeException:连接已被同级关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试从我的应用访问"https" Web服务时,它给出了" javax.net.ssl.SSLHandshakeException:连接被同级关闭"错误.相同的Web服务可以在Chrome浏览器中正常运行.

When I am trying to access a 'https' web service from my app , it is giving a 'javax.net.ssl.SSLHandshakeException: Connection closed by peer' error. The same Web Service works fine in the Chrome browser through.

仅在Android 7.0上会发生此问题,在Android 6.0及更高版本中工作正常5.0.

This issue is happening only on Android 7.0, It works fine in Android 6.0 & 5.0.

服务器已通过CA认证,而不是自签名的.

The Server is CA certified , not self-signed.

推荐答案

我必须使用扩展的SSLSocket类来包括所有协议和密码套件,以解决此问题.解决方案在于GetProtocolList()& GetCipherList()

I had to use the extended SSLSocket class to include all Protocols and Cipher Suites in order to overcome this issue . The solution lies in the 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;
}

SSLSocketFactoryExtended类文件

SSLSocketFactoryExtended Class file

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()]);
    }
}

这篇关于Android 7.0:"javax.net.ssl.SSLHandshakeException:连接已被同级关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆