Https学习

---来自慕课网学习笔记

Https会校验相关证书

在网站中可通过F12-->Security查相关证书

  • CA证书: github

 

github 证书是CA 签署的或者CA某个中间机构签署(CA证书价格昂贵)

此处为证书链 

操作系统 会默认存着的根证书的信息-->通过信息可以校验出来

我们当前网站 证书是否是ca颁发的 是否安全

  • 自签名证书

12306:

12306不是ca签署的 是自签名的 不被信任签发
自签名会给客户端提供一个证书下载地方(下载安装根证书)
证书导入电脑作为被信任列表 

Https案例:

android项目结构 

package com.example.https;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


import com.example.https;

public class HttpActivity extends AppCompatActivity {
    private TextView tv_result;
    private Button btn_send;
    private EditText et_input;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    private void initView(){
        tv_result = findViewById(R.id.tv_result);
        btn_send = findViewById(R.id.btn_send);
        et_input = findViewById(R.id.et_input);
        btn_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String s = et_input.getText().toString();
                if(TextUtils.isEmpty(s)){
                    return;
                }
                HttpsUtils.doGet(MainActivity.this,s, new HttpUtils.HttpListener() {
                    @Override
                    public void onSuccess(String content) {
                        tv_result.setText(content);
                    }

                    @Override
                    public void onFail(Exception ex) {
                        ex.printStackTrace();
                    }
                });

            }
        });
    }


}
package com.example.https;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

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

public class HttpsUtils {
    public interface HttpListener{
        void onSuccess(String content);
        void onFail(Exception ex);
    }
    private static Handler uiHandler = new Handler(Looper.getMainLooper());
    public static void doGet(final Context context, final String urlStr, final HttpUtils.HttpListener listener){
        new Thread(){
            @Override
            public void run() {
                InputStream is = null;
                try {
                    URL url = new URL(urlStr);
                    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
                    //初始化sslContext
                    SSLContext sslContext = SSLContext.getInstance("TLS");

                    X509Certificate serverCert = getCert(context);
                    TrustManager[] trustManagers = {new MyX509TrustManager(serverCert)};//被信任的对象
                    sslContext.init(null,trustManagers,new SecureRandom());
                    connection.setSSLSocketFactory(sslContext.getSocketFactory());
                    connection.setHostnameVerifier(new HostnameVerifier() {//对域名校验
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                            HostnameVerifier defaultHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();//拿到验证域名对象
                            return defaultHostnameVerifier.verify("kyfw.12306.cn",session);//return true不安全
                        }
                    });

                    connection.setDoInput(true);
                    connection.setDoOutput(true);
                    connection.setRequestMethod("GET");
                    connection.setReadTimeout(5000);
                    connection.setConnectTimeout(5000);
                    connection.connect();
                    //经验 乱码问题 页面默认UTF-8格式,读取也是UTF-8格式, 但utf-8默认变长 有可能某个汉字从缓冲区2047开始
                    //解决方案 1. byte先读到byteArray里面去 一次性处理再转String
                    //2.使用char来读取
                    is = connection.getInputStream();
//                    byte[] buf = new byte[2048];
                    InputStreamReader isr = new InputStreamReader(is);
                    char[] buf = new char[2048];
                    int len = -1;
                    final StringBuilder content = new StringBuilder();
                    while ((len = isr.read(buf))!=-1){
                        content.append(new String(buf,0,len));
                    }
                    uiHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            listener.onSuccess(content.toString());
                        }
                    });
                } catch (Exception e) {
                    listener.onFail(e);
                }finally {
                    if(is!=null){
                        try {
                            is.close();
                        } catch (IOException e) {
                            // ignore
                        }
                    }
                }
            }
        }.start();
    }
    public static X509Certificate getCert(Context context){
        try {
            InputStream is = context.getAssets().open("srca.cer");
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            return (X509Certificate) certificateFactory.generateCertificate(is);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        }
        return null;
    }
}
package com.example.https;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class MyX509TrustManager implements X509TrustManager{
    private X509Certificate mServerCert;

    public MyX509TrustManager(X509Certificate mServerCert) {
        this.mServerCert = mServerCert;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

    }
    //做单向校验可以只check服务器可信程度
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        //如果此处无任何代码 默认信任所有 server证书 但发挥不出安全性
        //正确处理方式如下 证书校验
        for(X509Certificate certificate:chain){
            certificate.checkValidity();//检查证书合法性 过期
            try {
                certificate.verify(mServerCert.getPublicKey());//传入server端证书公钥public key ,此处为与我们预设证书进行校验
            } catch (Exception e) {//如果证书正常不会抛Exception
                throw new CertificateException(e);
            }
        }
    }

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

访问12306显示效果:

证书验证另一种写法:

两种写法对比:

第一种证书由自己验证

第二种 通过证书生成 相关信息 keystore,由系统完成校验

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值