Android解决okhttpUtils框架无法在4.4.4以下系统访问https协议的问题

         公司因为网络安全的问题,将http协议换成了https协议,之前使用的okhttputils包在4.4.4以下的安卓系统中访问https协议的接口会报错,提示我因为没有ssl协议的问题。

         起初我以为是我自己的框架问题,因为用习惯了okhttpuitls框架,不想更换。就去github上面查找了(推荐dependencies在添加github上面的托管项目,而不要下载一个第三方项目去关联,因为在github上面会有维护,而且这样子代码看起来整洁。一般挑选框架,直接搜索之后选择星星最多的就好了。一般都是好东西),发现上面星星数量最多的是样神的。链接https://github.com/hongyangAndroid/okhttputils。按照上面所说的初始化兼容https的方法,发现还是无法在安卓4.4.4以下的系统中访问https。

        于是我去网上查找了一个SSl协议的工具类(以下工具类直接复制使用就好)

package com.baosheng.boosoo_ktv.Util;

import android.os.Build;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;

/**
 * Created by kkk on 2017/5/12.
 * 让安卓4.4.4以下的系统支持TLS协议,方法加入okhttp中
 */

public class SSLSocketFactoryCompat extends SSLSocketFactory {
    private SSLSocketFactory defaultFactory;
    // Android 5.0+ (API level21) provides reasonable default settings
    // but it still allows SSLv3
    // https://developer.android.com/about/versions/android-5.0-changes.html#ssl
    static String protocols[] = null, cipherSuites[] = null;
    static {
        try {
            SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
            if (socket != null) {
                /* set reasonable protocol versions */
                // - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0)
                // - remove all SSL versions (especially SSLv3) because they're insecure now
                List<String> protocols = new LinkedList<>();
                for (String protocol : socket.getSupportedProtocols())
                    if (!protocol.toUpperCase().contains("SSL"))
                        protocols.add(protocol);
                SSLSocketFactoryCompat.protocols = protocols.toArray(new String[protocols.size()]);
                /* set up reasonable cipher suites */
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                    // choose known secure cipher suites
                    List<String> allowedCiphers = Arrays.asList(
                            // TLS 1.2
                            "TLS_RSA_WITH_AES_256_GCM_SHA384",
                            "TLS_RSA_WITH_AES_128_GCM_SHA256",
                            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
                            "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
                            "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
                            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
                            "TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256",
                            // maximum interoperability
                            "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
                            "TLS_RSA_WITH_AES_128_CBC_SHA",
                            // additionally
                            "TLS_RSA_WITH_AES_256_CBC_SHA",
                            "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
                            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
                            "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
                            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
                    List<String> availableCiphers = Arrays.asList(socket.getSupportedCipherSuites());
                    // take all allowed ciphers that are available and put them into preferredCiphers
                    HashSet<String> preferredCiphers = new HashSet<>(allowedCiphers);
                    preferredCiphers.retainAll(availableCiphers);
                    /* For maximum security, preferredCiphers should *replace* enabled ciphers (thus disabling
                     * ciphers which are enabled by default, but have become unsecure), but I guess for
                     * the security level of DAVdroid and maximum compatibility, disabling of insecure
                     * ciphers should be a server-side task */
                    // add preferred ciphers to enabled ciphers
                    HashSet<String> enabledCiphers = preferredCiphers;
                    enabledCiphers.addAll(new HashSet<>(Arrays.asList(socket.getEnabledCipherSuites())));
                    SSLSocketFactoryCompat.cipherSuites = enabledCiphers.toArray(new String[enabledCiphers.size()]);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public SSLSocketFactoryCompat(X509TrustManager tm) {
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, (tm != null) ? new X509TrustManager[] { tm } : null, null);
            defaultFactory = sslContext.getSocketFactory();
        } catch (GeneralSecurityException e) {
            throw new AssertionError(); // The system has no TLS. Just give up.
        }
    }
    private void upgradeTLS(SSLSocket ssl) {
        // Android 5.0+ (API level21) provides reasonable default settings
        // but it still allows SSLv3
        // https://developer.android.com/about/versions/android-5.0-changes.html#ssl
        if (protocols != null) {
            ssl.setEnabledProtocols(protocols);
        }
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && cipherSuites != null) {
            ssl.setEnabledCipherSuites(cipherSuites);
        }
    }
    @Override
    public String[] getDefaultCipherSuites() {
        return cipherSuites;
    }
    @Override
    public String[] getSupportedCipherSuites() {
        return cipherSuites;
    }
    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        Socket ssl = defaultFactory.createSocket(s, host, port, autoClose);
        if (ssl instanceof SSLSocket)
            upgradeTLS((SSLSocket)ssl);
        return ssl;
    }
    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        Socket ssl = defaultFactory.createSocket(host, port);
        if (ssl instanceof SSLSocket)
            upgradeTLS((SSLSocket)ssl);
        return ssl;
    }
    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort);
        if (ssl instanceof SSLSocket)
            upgradeTLS((SSLSocket)ssl);
        return ssl;
    }
    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        Socket ssl = defaultFactory.createSocket(host, port);
        if (ssl instanceof SSLSocket)
            upgradeTLS((SSLSocket)ssl);
        return ssl;
    }
    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort);
        if (ssl instanceof SSLSocket)
            upgradeTLS((SSLSocket)ssl);
        return ssl;
    }
}
         然后在Application初始化这个ssl协议进入okhttputils框架中

/*
初始化添加ssl协议(解决安卓4.4.4中okhttp不能访问https的问题)
 */
private void intiSSL() {
    // 自定义一个信任所有证书的TrustManager
    final X509TrustManager trustAllCert =
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[]{};
                }
            };

    final SSLSocketFactory sslSocketFactory = new SSLSocketFactoryCompat(trustAllCert);

    HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(null, null, null);
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, trustAllCert)
            //其他配置
            .build();
    OkHttpUtils.initClient(okHttpClient);
}
            顺利的解决了这个问题。随便符下一些其他的代码,如果访问过程中有出错,可以对照我这边的代码。

         

OkHttpUtils.get()
        .url("https:...")
        .build()
        .execute(new UpdateCallBack() {
            @Override
            public void onError(Call call, Exception e, int id) {
                Log.e("onError", e.getMessage());
            }

            @Override
            public void onResponse(Updateinfo response, int id) {
                Log.e("onResponse", response.getData().getApkurl());
            }
        });

package com.baosheng.boosoo_ktv.Httpcallbcak;

import com.baosheng.boosoo_ktv.info.Updateinfo;
import com.google.gson.Gson;
import com.zhy.http.okhttp.callback.Callback;

import java.io.IOException;

import okhttp3.Response;

/**
 * Created by Administrator on 2016/6/12.
 */
public abstract class UpdateCallBack extends Callback<Updateinfo> {
    public Updateinfo parseNetworkResponse(Response response, int id) throws IOException {
        String string = response.body().string();
        Updateinfo goods = new Gson().fromJson(string, Updateinfo.class);
        return goods;
    }
}
package com.baosheng.boosoo_ktv.info;

/**
 * Created by kkk on 2017/5/12.
 */

public class Updateinfo {

    /**
     * data : {"apkurl":"http://singerimg.cavca.net/4c316e7c26c34d68b85f6da2e11d7a00.apk","desic":"1.发生的。2.12132231。3.阿斯顿发生。4.打撒","isenforce":0,"title":"版本更新","version":"1.3"}
     * msg : success
     * status_code : 200
     */

    private DataBean data;
    private String msg;
    private String status_code;

    public DataBean getData() {
        return data;
    }

    public void setData(DataBean data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getStatus_code() {
        return status_code;
    }

    public void setStatus_code(String status_code) {
        this.status_code = status_code;
    }

    public static class DataBean {
        /**
         * apkurl : http://singerimg.cavca.net/4c316e7c26c34d68b85f6da2e11d7a00.apk
         * desic : 1.发生的。2.12132231。3.阿斯顿发生。4.打撒
         * isenforce : 0
         * title : 版本更新
         * version : 1.3
         */

        private String apkurl;
        private String desic;
        private int isenforce;
        private String title;
        private String version;

        public String getApkurl() {
            return apkurl;
        }

        public void setApkurl(String apkurl) {
            this.apkurl = apkurl;
        }

        public String getDesic() {
            return desic;
        }

        public void setDesic(String desic) {
            this.desic = desic;
        }

        public int getIsenforce() {
            return isenforce;
        }

        public void setIsenforce(int isenforce) {
            this.isenforce = isenforce;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_30267253/article/details/72417399