Android 에서 Https 통신 실현클 라 이언 트 단 방향 인증 검사 브로커 공격 방지

23252 단어 네트워크 통신
HTTPS 를 도입 하 는 것 은 HTTP 가 가 져 온 세 가지 문 제 를 해결 하기 위해 서 입 니 다.
  • HTTP 는 명문 전송 으로 데이터 가 도 둑 맞 기 쉬 우 므 로 데이터 가 도중에 도 둑 맞 는 것 을 방지 하기 위해 데 이 터 를 암호 화해 야 한다
  • 서버 신분 을 인증 하고 데이터 가 정확 한 서버 로 전송 되도록 확보한다
  • 데이터 의 완전 성 을 유지 하고 데이터 가 전송 중 에 바 뀌 는 것 을 방지 합 니 다. 예 를 들 어 중개인 의 공격 등 이 있 기 때문에 이 장 은 주로 OkHttp 나 HttpUrl Connection 을 사용 하여 자체 인증 서 를 방문 하 는 방법 을 설명 합 니 다.

  • 인증서 검사 설정
    앞의 블 로그 에는 인증 서 를 돌아 가 는 방법 이 적 혀 있 습 니 다. 그것 은 안전 하지 않 은 방문 방식 으로 중개인 의 공격 을 받 기 쉬 우 므 로 클 라 이언 트 는 양 방향 인증서 검 사 를 통 해 클 라 이언 트 의 합 법성 을 확보 해 야 합 니 다.
    private static SSLSocketFactory setCertificates(InputStream... certificates) {
       try {
           CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
           KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
           keyStore.load(null);
           int index = 0;
           for (InputStream certificate : certificates) {
               String certificateAlias = Integer.toString(index++);
               keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
               if (certificate != null) {
                   certificate.close();
               }
           }
           SSLContext sslContext = SSLContext.getInstance("TLS");
           TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
           trustManagerFactory.init(keyStore);
           sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
           return sslContext.getSocketFactory();
       } catch (Exception e) {
           e.printStackTrace();
           return null;
       }
    }
    

    도 메 인 이름 검사 설정
    도 메 인 이름 검 사 는 trustHosts 배열 을 설정 해 야 합 니 다. 현재 도 메 인 이름 이 이 배열 의 하나 와 일치 하면 true 로 돌아 갈 수 있 습 니 다. 그렇지 않 으 면 false 로 돌아 갈 수 있 습 니 다.
    //  HostnameVerifier
    public static HostnameVerifier getHostnameVerifier(final JSONArray trustHosts) {
        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String host, SSLSession sslSession) {
                if (trustHosts == null || trustHosts.length() == 0) {
                    return false;
                }
                try {
                    for (int i = 0; i < trustHosts.length(); i++) {
                        String trustHost = trustHosts.getString(i);
                        if (host.equalsIgnoreCase(trustHost)) {
                            return true;
                        }
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return false;
            }
        };
        return hostnameVerifier;
    }
    

    호출 인터페이스
    //    SSLSocketFactory
    public static SSLSocketFactory getSSLSocketFactory(InputStream cerIn) {
        try {
            SSLSocketFactory factory = setCertificates(cerIn);
            return factory;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    

    OkHttp 신뢰 인증서 설정
    JSONArray trustHosts= new JSONArray();
    jsonArray.put("192.169.15.110");
    jsonArray.put("192.169.15.111");
    OkHttpClient.Builder builder = new OkHttpClient.Builder();
    builder.sslSocketFactory(SSLSocketCert.getSSLSocketFactory(context.getAssets().open("jetty.crt")));
    builder.hostnameVerifier(SSLSocketCert.getHostnameVerifier(trustHosts));
    

    HttpURLConnection 신뢰 인증서 설정
    JSONArray trustHosts= new JSONArray();
    jsonArray.put("192.169.15.110");
    jsonArray.put("192.169.15.111");
    URL url = new URL(fileUrl);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    ((HttpsURLConnection) conn).setSSLSocketFactory(SSLSocketCert.getSSLSocketFactory(context.getAssets().open("jetty.crt")));
    ((HttpsURLConnection) conn).setHostnameVerifier(SSLSocketCert.getHostnameVerifier(trustHosts));
    

    인증서 문자열 사용
    안 드 로 이 드 프로젝트 assets 에 인증 서 를 올 려 놓 았 습 니 다. 인증서 의 내용 을 프로그램 에 유도 할 수 있 습 니 다.
    private String CER_STR = "-----BEGIN CERTIFICATE-----
    "
    + "MIICmjCCAgOgAwIBAgIIbyZr5/jKH6QwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ04xKTAn
    "
    + "BgNVBAoTIFNpbm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMB4X
    "
    + "DTA5MDUyNTA2NTYwMFoXDTI5MDUyMDA2NTYwMFowRzELMAkGA1UEBhMCQ04xKTAnBgNVBAoTIFNp
    "
    + "bm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMIGfMA0GCSqGSIb3
    "
    + "DQEBAQUAA4GNADCBiQKBgQDMpbNeb34p0GvLkZ6t72/OOba4mX2K/eZRWFfnuk8e5jKDH+9BgCb2
    "
    + "9bSotqPqTbxXWPxIOz8EjyUO3bfR5pQ8ovNTOlks2rS5BdMhoi4sUjCKi5ELiqtyww/XgY5iFqv6
    "
    + "D4Pw9QvOUcdRVSbPWo1DwMmH75It6pk/rARIFHEjWwIDAQABo4GOMIGLMB8GA1UdIwQYMBaAFHle
    "
    + "tne34lKDQ+3HUYhMY4UsAENYMAwGA1UdEwQFMAMBAf8wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDov
    "
    + "LzE5Mi4xNjguOS4xNDkvY3JsMS5jcmwwCwYDVR0PBAQDAgH+MB0GA1UdDgQWBBR5XrZ3t+JSg0Pt
    "
    + "x1GITGOFLABDWDANBgkqhkiG9w0BAQUFAAOBgQDGrAm2U/of1LbOnG2bnnQtgcVaBXiVJF8LKPaV
    "
    + "23XQ96HU8xfgSZMJS6U00WHAI7zp0q208RSUft9wDq9ee///VOhzR6Tebg9QfyPSohkBrhXQenvQ
    "
    + "og555S+C3eJAAVeNCTeMS3N/M5hzBRJAoffn3qoYdAO1Q8bTguOi+2849A==
    "
    + "-----END CERTIFICATE-----";

    그리고 다시 호출 하 다
    JSONArray trustHosts= new JSONArray();
    jsonArray.put("192.169.15.110");
    jsonArray.put("192.169.15.111");
    OkHttpClient.Builder builder = new OkHttpClient.Builder();
    builder.sslSocketFactory(SSLSocketCert.getSSLSocketFactory(new Buffer().writeUtf8(CER_STR).inputStream()));
    builder.hostnameVerifier(SSLSocketCert.getHostnameVerifier(trustHosts));
    

    도구 클래스 업로드 주소https://download.csdn.net/download/u010982507/10905059 학습 참고https://blog.csdn.net/lmj623565791/article/details/48129405

    좋은 웹페이지 즐겨찾기