【Android】支持https接口调用的简单证书校验

8 篇文章 0 订阅
3 篇文章 0 订阅

我们在做https接口支持时,用到了X509证书。然后针对X509的证书验证,线下环境不做校验,线上环境仅仅做单向的hostname校验。完善的校验应该包括客户端和服务端的证书校验。

package com.xxx.utils;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class HttpsTrustManager implements X509TrustManager {

    private static TrustManager[]          trustManagers;
    private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};

    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates,
                                   String s) throws java.security.cert.CertificateException {
        //验证客户端证书,不通过则抛出异常
    }

    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates,
                                   String s) throws java.security.cert.CertificateException {
        //验证服务端证书,不通过则抛出异常
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return _AcceptedIssuers;
    }

    public static void allowAllSSL() {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                // FIXME 线上要做HTTPS证书信息验证
                boolean isTrust = false;
                //如果线下则默认不校验,isOnline自己做控制
                if (!isOnline) {
                    isTrust = true;
                    LogUtil.d("线下环境,证书不校验。");
                } else {
                    try {
                        //获得证书
                        Certificate[] certificates = session.getPeerCertificates();
                        if (certificates != null && certificates.length > 0) {
                            Certificate certificate = certificates[0];
                            //做X509证书信息获取
                            if (certificate instanceof X509Certificate) {
                                X509Certificate x509Certificate = (X509Certificate) certificate;
                                Collection<List<?>> subjectAlternativeNames = x509Certificate
                                    .getSubjectAlternativeNames();
                                //获得证书信息
                                String names = Arrays
                                    .deepToString(subjectAlternativeNames.toArray());
                                //校验host信息
                                isTrust = names.contains(hostname);
                            }
                        }
                    } catch (SSLPeerUnverifiedException e) {
                        LogUtil.e("on error when verify SSL." + e.getMessage());
                    } catch (CertificateParsingException e) {
                        LogUtil.e("on error when verify SSL." + e.getMessage());
                    }
                }
                if (!isTrust) {
                    LogUtil.d("证书校验不通过,请核查~(hostname=" + hostname + ")");
                }
                return isTrust;
            }
        });

        SSLContext context = null;
        if (trustManagers == null) {
            trustManagers = new TrustManager[] { new HttpsTrustManager() };
        }

        try {
            context = SSLContext.getInstance("TLS");
            context.init(null, trustManagers, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
    }

}

然后在网络请求之前调用如下代码:

        //添加https支持
        HttpsTrustManager.allowAllSSL();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中调用HTTPS接口并忽略证书,可以通过使用自定义的信任管理器来实现。证书验证是HTTPS通信的一部分,目的是确保通信双方的身份和保障通信的安全性。然而,有时我们需要在测试环境或特殊情况下绕过证书验证。 首先,我们需要创建一个自定义的信任管理器,该管理器将忽略证书验证。以下是一个简单的示例: ```java import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import javax.net.ssl.*; public class SSLUtil { public static void ignoreSSL() throws NoSuchAlgorithmException, KeyManagementException { TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); } } ``` 接下来,在实际调用HTTPS接口之前,我们需要在代码中调用`ignoreSSL()`方法: ```java public class Main { public static void main(String[] args) { try { SSLUtil.ignoreSSL(); // 在这里进行HTTPS接口调用,忽略证书验证 // ... } catch (Exception e) { e.printStackTrace(); } } } ``` 通过使用上述代码,我们可以成功忽略证书验证,并在Java中调用HTTPS接口。请注意,在生产环境中,强烈建议不要忽略证书验证,以确保通信的安全性。仅在特殊情况下,例如调试或开发环境下使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值