Okhttp访问https 12306


下面写的类调用其getInstance方法即可获得可以访问https的HttpClient对象,使用如下:

HTTPUtils utils = new HTTPUtils(getApplicationContext);

OkHttpClient client = utils.getInstance();

在需要操作的界面获取client对象后,我们就可以访问12306了。

关于HTTPS参考如下文章:

OKHTTP通信使用(三)HTTPS

Android Https相关完全解析 当OkHttp遇到Https

package utils;

import android.content.Context;

import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Collection;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;

/**
 * 用于访问https网络
 */
public final class HTTPSUtils {
    public OkHttpClient client = null;
    public Context mContext;
    public static HTTPSUtils httpsUtils = null;
    X509TrustManager trustManager;
    SSLSocketFactory sslSocketFactory;

    /**
     * 初始化HTTPS,添加信任证书
     *
     * @param context
     */
    public HTTPSUtils(Context context) {
        mContext = context;
        final InputStream inputStream;
        try {
            //获取放在assets下面的12306的证书
            inputStream = mContext.getAssets().open("srca.cer"); // 得到证书的输入流
            try {
                trustManager = trustManagerForCertificates(inputStream);//以流的方式读入证书
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, new TrustManager[]{trustManager}, null);
                sslSocketFactory = sslContext.getSocketFactory();
            } catch (GeneralSecurityException e) {
                throw new RuntimeException(e);
            }
            client = new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory).build();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 返回获取ssl后的okhttpclient,用于请求访问https
     *
     * @param context
     * @return okhttpclient
     */
    public OkHttpClient getInstance(Context context) {
        if (client == null) {
            httpsUtils = new HTTPSUtils(context);
            if (httpsUtils.client != null) {
                return httpsUtils.client;
            }
        }
        return client;
    }
    /**
     * 以流的方式添加信任证书
     */
    /**
     * Returns a trust manager that trusts {@code certificates} and none other. HTTPS services whose
     * certificates have not been signed by these certificates will fail with a {@code
     * SSLHandshakeException}.
     * <p/>
     * <p>This can be used to replace the host platform's built-in trusted certificates with a custom
     * set. This is useful in development where certificate authority-trusted certificates aren't
     * available. Or in production, to avoid reliance on third-party certificate authorities.
     * <p/>
     * <p/>
     * <h3>Warning: Customizing Trusted Certificates is Dangerous!</h3>
     * <p/>
     * <p>Relying on your own trusted certificates limits your server team's ability to update their
     * TLS certificates. By installing a specific set of trusted certificates, you take on additional
     * operational complexity and limit your ability to migrate between certificate authorities. Do
     * not use custom trusted certificates in production without the blessing of your server's TLS
     * administrator.
     */
    private X509TrustManager trustManagerForCertificates(InputStream in)
            throws GeneralSecurityException {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
        if (certificates.isEmpty()) {
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }

        // Put the certificates a key store.
        char[] password = "password".toCharArray(); // Any password will work.
        KeyStore keyStore = newEmptyKeyStore(password);
        int index = 0;
        for (Certificate certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificate);
        }

        // Use it to build an X509 trust manager.
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:"
                    + Arrays.toString(trustManagers));
        }
        return (X509TrustManager) trustManagers[0];
    }


    /**
     * 添加password
     *
     * @param password
     * @return
     * @throws GeneralSecurityException
     */
    private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); // 这里添加自定义的密码,默认
            InputStream in = null; // By convention, 'null' creates an empty key store.
            keyStore.load(in, password);
            return keyStore;
        } catch (IOException e) {
            throw new AssertionError(e);
        }
    }


}

要使用OkHttp3进行HTTPS访问,您需要遵循以下步骤: 1. 添加依赖 在您的项目中添加以下依赖: ```gradle implementation 'com.squareup.okhttp3:okhttp:4.9.0' ``` 2. 创建OkHttpClient对象 ```java OkHttpClient client = new OkHttpClient.Builder() .build(); ``` 3. 创建Request对象 ```java Request request = new Request.Builder() .url("https://example.com") .build(); ``` 请注意,您需要使用https而不是http作为URL协议。 4. 发送请求 ```java try (Response response = client.newCall(request).execute()) { // 处理响应 String responseData = response.body().string(); } catch (IOException e) { e.printStackTrace(); } ``` 在使用HTTPS时,您可能需要使用自定义的证书或信任存储来验证服务器的身份。这可以通过以下方式实现: 1. 创建TrustManager ```java TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }; ``` 这个TrustManager将接受所有证书而不验证它们的可信度,这是不安全的。在生产环境中,您应该使用自己的TrustManager来验证证书。 2. 创建SSLContext ```java SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new SecureRandom()); ``` 3. 创建SSLSocketFactory ```java SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); ``` 4. 创建OkHttpClient ```java OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]) .hostnameVerifier((hostname, session) -> true) .build(); ``` 在这个例子中,我们使用了之前创建的TrustManager和SSLContext来生成一个自定义的SSLSocketFactory。我们还使用了一个自定义的hostnameVerifier,它将接受所有主机名而不验证它们的可信度。这也是不安全的,您应该使用自己的hostnameVerifier来验证主机名。 完成后,您可以像往常一样使用OkHttpClient来发送HTTPS请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值