Https协议

转载请注明出处:http://blog.csdn.net/huaiyiheyuan/article/details/53583253

一、https就是在http ,和tcp层之间添加了一层 ssl保护装置(个人理解)
1 、client给网站发送支持的算法
2、 网站选择算法 ,把包含公钥、网址的证书 发送给client ,
3、 client 验证证书 真伪、生成随机密码,用网站给的公钥加密发送
给网站
4、网站 hash认证 用对应的私钥解密,得到密码,给client回馈,握
手结束,用密码发送数据

这里面最重要的是客户端要认证服务器端的证书的有效性、
如果网站的证书没有经过认证(自己生成的证书),那么客户端就要验证证书

图形化表达 :http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html

二、Android Https请求
1、先找个现成的测试,卖火车票的,先去12306下载证书 http://www.12306.cn/mormhweb/ggxxfw/wbyyzj/201106/srca12306.zip (最好别安装到电脑原因点这里)
2、访问网站
1) 把下载的srca.cer放到assets目录下面,接下来就是搬代码了
https://developer.android.com/training/articles/security-ssl.html?hl=zh-cn

private void initCA() throws Exception {
        // Load CAs from an InputStream
        // could be from a resource or ByteArrayInputStream or ...)
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new BufferedInputStream(getAssets().open("srca.cer"));
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
            System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }
        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);
        // Create an SSLContext that uses our TrustManager
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
 }

2)用本地字符串代替证书
使用keytool工具到srca.cer目录下 : keytool -printcert -rfc -file srca.cer

这里写图片描述
需要修改是的是

  *InputStream caInput = new BufferedInputStream(getAssets().open("srca.cer"));*
        //替换成
        InputStream caInput = new ByteArrayInputStream(String_CAs.getBytes());

注意 :
String_CAs = —–BEGIN CERTIFICATE—–
MIICmjCCAgOgAwIBA …
—–END CERTIFICATE—–
前后两个标签也需要
3) HttpsURLConnection请求数据

 Executors.newCachedThreadPool().submit(new Runnable() {
            @Override
            public void run() {
                try {
                    initCA();
                    String ur = "https://kyfw.12306.cn/otn/";
//                    String ur = "https://192.168.0.126:8443/img/pic1.jpg";
                    URL url = new URL(ur);
                    //打开该URL对应的资源的输入流
                    HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
                    urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());////前面initCA()方法就是为这里铺垫
//                    urlConnection.setHostnameVerifier(hostnameVerifier);
                    InputStream in = urlConnection.getInputStream();
                    BufferedReader bf = new BufferedReader(new InputStreamReader(in));

                    StringBuilder sb = new StringBuilder();
                    String s;
                    while ((s = bf.readLine()) != null) {
                        sb.append(s + "\n");
                    }
                    Message msg = Message.obtain();
                    msg.obj = sb;
                    handler.sendMessage(msg);
                    bf.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

然后就看到了图上打印的脚本了
这里写图片描述

三、配置子签名证书
上面是现成可以用的,我们开发者自己如何生成证书呢?
1、keytool生成证书

 jon@jon-thinkpad:~/软件/server$ keytool -genkey -alias jon_server -keyalg RSA -keystore jon_server.jks -validity 3600 -storepass 123456
您的名字与姓氏是什么?
  [Unknown]:  zh
您的组织单位名称是什么?
  [Unknown]:  z
您的组织名称是什么?
  [Unknown]:  z
您所在的城市或区域名称是什么?
  [Unknown]:  z 
您所在的州或省份名称是什么?
  [Unknown]:  z
该单位的两字母国家代码是什么
  [Unknown]:  cn
CN=zh, OU=z, O=z, L=z, ST=z, C=cn 正确吗?
  []:  是

输入<jon_server>的主密码
    (如果和 keystore 密码相同,按回车):  

这样就生成了 jon_server.jks 密码都是123456(android的密钥也可以这样生成),接下来签发证书

~/软件/server$ keytool -export -alias jon_server -file jon_server.cer  -keystore jon_server.jks  -storepass 123456

生成的jon_server.cer

2、tomacat配置证书
1) 先下载tomcat(apache-tomcat-8.5.9.tar.gz我下的版本),到bin目录下运行startup.sh(linux环境),http://localhost:8080/测试下环境
2)打开config目录下的server.xml,在<Service name="Catalina">节点内部(和Connector平行),添加

<Connector SSLEnabled="true" acceptCount="100" 
    disableUploadTimeout="true" enableLookups="true" keystoreFile="/home/jon/软件/server/jon_server.jks" keystorePass="123456"   
    maxSpareThreads="75" clientAuth="false"        maxThreads="200" minSpareThreads="5" port="8443" 
    protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" secure="true" sslProtocol="TLS"
 /> 

keystoreFIle :jon_server.jks文件的绝对路径
3)启动tomcat,浏览器输入 https://localhost:8443/
看到这个页面 这里写图片描述
firfox添加例外
这里写图片描述
恭喜你配置OK

也可以在webapps 的 Root根目录下添加内容,我创建了img文件夹,里面添加了一些图片,然后访问 https://localhost:8443/img/pic1.jpg

4)客户端访问
这个配置和12306现成的证书读取配置是一样的,需要客户端和服务端在一个局域网内

       initCA();
                    String ur = "https://192.168.1.125:8443/img/pic1.jpg";
                    URL url = new URL(ur);
                    //打开该URL对应的资源的输入流
                    HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
                    urlConnection.setSSLSocketFactory(sslContext.getSocketFactory()); //前面initCA()方法就是为这里铺垫
                    urlConnection.setHostnameVerifier(hostnameVerifier);  //域名验证
                    InputStream in = urlConnection.getInputStream();
                    BufferedReader bf = new BufferedReader(new InputStreamReader(in));

                    Bitmap bitmp = BitmapFactory.decodeStream(in);
                    Message msg = Message.obtain();
                    msg.obj = bitmp;
                    handler.sendMessage(msg);
                    bf.close();

  HostnameVerifier hostnameVerifier = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            // Open SSLSocket directly to gmail.com
            return true;
        }
    };

只需要域名验证
这里写图片描述

三、https双向验证

1、SSL双向认证具体过程

① 浏览器发送一个连接请求给安全服务器。

② 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。

③ 客户浏览器检查服务器送过来的证书是否是由自己信赖的CA中心(如沃通CA)所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的,询问客户是否需要继续。

④ 接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。

⑤ 服务器要求客户发送客户自己的证书。收到后,服务器验证客户的证书,如果没有通过验证,拒绝连接;如果通过验证,服务器获得用户的公钥。

⑥ 客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。

⑦ 服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。

⑧ 浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。

⑨ 服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。

⑩ 服务器、浏览器接下来的通讯都是用对称密码方案,对称密钥是加过密的。

双向认证则是需要服务端与客户端提供身份认证,只能是服务端允许的客户能去访问,安全性相对于要高一些。

2、配置tomcat
1)和上面一样生成客户端jon_client.jks文件,和CA

keytool -genkey -alias jon_client  -keyalg RSA -keystore jon_client.jks -validity 3600 -storepass 123456

keytool -export -alias jon_client -file jon_client.cer  -keystore jon_client.jks  -storepass 123456

//为了让tomcat运行 还需要把cer添加到jks文件生成 jon_client_for_sever.jks

keytool -import -alias jon_client  -file jon_client.cer -keystore jon_client_for_sever.jks

2)修改server.xml
在之前节点下 修改添加下面

   clientAuth="true"    truststoreFile ="/home/jon/软 件/server/jon_client_for_sever.jks" 
 把浏览器的例外清除重新来过 ,
 在firfox输入 https://localhost:8443/  然后添加例外,
接着就会看到这个界面 
![这里写图片描述](https://img-blog.csdn.net/20161224194127300?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHVhaXlpaGV5dWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

3)配置客户端

 sslContext.init(null, tmf.getTrustManagers(), null);//第一个参数提供客户端身份认证



   /**
         * 双向认证
         */
        KeyStore clientKeyStore = KeyStore.getInstance(keyStoreType);
        clientKeyStore.load(getAssets().open("jon_client.bks"), "123456".toCharArray());
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(clientKeyStore, "123456".toCharArray());
        sslContext.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);

正常情况应该在asset目录添加 jon_client.jks,但是android客户端不支持,用 portecle工具,把jks文件专程bks文件
然后跑起来就可以接受到数据了
代码 :https://github.com/BlogForMe/DrugStore

参考:
http://blog.csdn.net/lmj623565791/article/details/48129405

https://program-think.blogspot.com/2014/11/https-ssl-tls-1.html

http://www.cnblogs.com/P_Chou/archive/2010/12/27/https-ssl-certification.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值