HTTPS访问中证书的处理

现在基本大家都在使用HTTPS,比如REST API, 或者其他类似的SOAP啥的。因为HTTP是明文传输太不安全了。使用HTTPS会有个比较麻烦的问题就是证书的处理。这里有几种证书的问题:

1. 如果判断HTTPS中的证书是否是正确的?所谓的正确有2种意思:

a. 证书是假的,并非权威机构签发的,比如自己做的测试证书。

b. 证书也是权威机构签发的,但并不是自己公司的。比如某个人向verisign公司买了一个证书,然后通过域名劫持啥的把某https站点引导到自己的服务器,并且使用自己购买的证书,从而收集用户的密码啥的。

2. 通常在开发阶段用的都是测试证书,那么很多https访问库,一看这个证书并不在当前机器的信任区,可能会直接丢出错误。

对于这些问题,其实解决起来还是蛮简单的,基本思路就是:获取证书信息,然后自己根据需求来进行处理。

这里使用C#做一个简单演示:

static public string ReadHTTPorHTTPSWithGet(string URL)
        {
            try
            {

                // combine HTTP request
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);

                // HTTP request header
                request.Method = "get";
                request.ContentType = "text/plain,charset=UTF-8";

                // try to get response from HTTP/HTTPS
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream ss = response.GetResponseStream();
                using (StreamReader reader = new StreamReader(ss, Encoding.UTF8))
                {
                    string data = reader.ReadToEnd();

                    return data;
                }
            }
            catch (Exception e)
            {
                string err = e.Message;
            }

            return "";
        }

如果使用上面的代码来访问https://www.baidu.com,没有问题可以成功得到结果,因为百度的证书是正式的,它是由verisign公司签发的,而verisign公司的根证书都是默认在机器的信任区的,大家可以打开证书管理器看一下(certmgr.msc)

可以看到这里有一堆的信任根证书,其中就有verisign公司的根证书(verisign公司是权威的,世界上用的大多数证书都是他们签发的,当然微软,苹果,谷歌等大公司也有一些权威根证书)。

百度的证书也是verisign公司签发的,所以没有问题。

我们可以创建来看一下百度的证书。为了查看百度的证书,需要自己提供一个System.Net.ICertificatePolicy的子类,重写虚函数

public bool CheckValidationResult(ServicePoint sp,

System.Security.Cryptography.X509Certificates.X509Certificate cert,

WebRequest req, int problem)

如:

    public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
    {
        public TrustAllCertificatePolicy()
        { }

        public bool CheckValidationResult(ServicePoint sp,
            System.Security.Cryptography.X509Certificates.X509Certificate cert,
            WebRequest req, int problem)
        {
            System.Console.WriteLine("name: " + cert.Subject);
            System.Console.WriteLine("issuer name: " + cert.Issuer);

            return true;
        }
    }

我们可以打出证书信息。

在访问https之前,替换成我们自己的类实例:

System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();

运行一下,就可以看到百度的证书信息:

可以看到百度的证书确实是verisign公司签发的,而verisign公司的根证书在信任区。所以验证没问题。

那么如果是自己的测试证书呢?

如果我们不提供自己的certificatePolicy类,那么怕是会丢出异常,说是证书不合法啥的。

其实原因很简单,因为默认的CertificatePolicy类会去检查证书是不是合法机构签发的。看上去类似:

        public bool CheckValidationResult(ServicePoint sp,
            System.Security.Cryptography.X509Certificates.X509Certificate cert,
            WebRequest req, int problem)
        {
            System.Console.WriteLine("name: " + cert.Subject);
            System.Console.WriteLine("issuer name: " + cert.Issuer);

            if (cert is in trusted area) return true;
            else return false;

        }

然后就出错了。

如果我们自己重写了CheckValidationResult,如:

        public bool CheckValidationResult(ServicePoint sp,
            System.Security.Cryptography.X509Certificates.X509Certificate cert,
            WebRequest req, int problem)
        {
            System.Console.WriteLine("name: " + cert.Subject);
            System.Console.WriteLine("issuer name: " + cert.Issuer);

            return true;
        }

如何什么证书都返回true那就ok了。如果我们在测试开发阶段使用测试证书,那么就可以这么做。然后等正式发布的时候(有正式证书了),就把这段代码去掉,这样程序就只认权威机构签发的证书了。另外还有个问题,如果为了防止域名被劫持,然后使用一个权威机构签发的另外一个证书。解决问题也很简单,就是重写CheckValidationResult函数,然后在里面得到证书的信息,看一下subject里面是不是自己公司的,如果是就返回true,否则返回false,这样就防止公司的https被中途拦截了。

完整代码:

这个例子里实现了GET和POST。可以直接运行,并且看百度的证书信息。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace TestHTTPS
{
    public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
    {
        public TrustAllCertificatePolicy()
        { }

        public bool CheckValidationResult(ServicePoint sp,
            System.Security.Cryptography.X509Certificates.X509Certificate cert,
            WebRequest req, int problem)
        {
            System.Console.WriteLine("name: " + cert.Subject);
            System.Console.WriteLine("issuer name: " + cert.Issuer);

            return true;
        }
    }

    class Program
    {
        static public string ReadHTTPorHTTPSWithGet(string URL)
        {
            try
            {
                System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();

                // combine HTTP request
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);

                // HTTP request header
                request.Method = "get";
                request.ContentType = "text/plain,charset=UTF-8";

                // try to get response from HTTP/HTTPS
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream ss = response.GetResponseStream();
                using (StreamReader reader = new StreamReader(ss, Encoding.UTF8))
                {
                    string data = reader.ReadToEnd();

                    return data;
                }
            }
            catch (Exception e)
            {
                string err = e.Message;
            }

            return "";
        }

        static public string ReadHTTPorHTTPSWithPost(string URL, string strPostdata)
        {
            try
            {
                System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();

                // combine HTTP request
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);

                // HTTP request header
                request.Method = "post";
                request.ContentType = "text/plain,charset=UTF-8";

                // HTTP request body
                byte[] buffer = Encoding.UTF8.GetBytes(strPostdata);
                request.ContentLength = buffer.Length;
                request.GetRequestStream().Write(buffer, 0, buffer.Length);

                // try to get response from HTTP/HTTPS
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream ss = response.GetResponseStream();
                using (StreamReader reader = new StreamReader(ss, Encoding.UTF8))
                {
                    string data = reader.ReadToEnd();

                    return data;
                }
            }
            catch (Exception e)
            {
                string err = e.Message;
            }

            return "";
        }

        static void Main(string[] args)
        {
            string ret = ReadHTTPorHTTPSWithGet("https://www.baidu.com");
            string ret2 = ReadHTTPorHTTPSWithGet("http://www.baidu.com");

            if (ret.Equals(ret2))
            {
                System.Console.WriteLine("success, results for http and https are same.");
            }
            else
            {
                System.Console.WriteLine("failed");
            }
        }
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-30 10:03:17

HTTPS访问中证书的处理的相关文章

Windows下Nginx配置SSL实现Https访问(包含证书生成)

Vincent.李 Windows下Nginx配置SSL实现Https访问(包含证书生成) Windows下Nginx配置SSL实现Https访问(包含证书生成) 首先要说明为什么要实现https? HTTP全名超文本传输协议,客户端据此获取服务器上的超文本内容.超文本内容则以HTML为主,客户端拿到HTML内容后可根据规范进行解析呈现.因此,HTTP主要负责的是"内容的请求和获取".问题就出在这部分.行监控.劫持.阻挡等行为很容易导致网站泄密,一些关键参数比如登录密码开发者会在客户端

IIS 6.0安装SSL数字证书实现https访问

https访问某个网站的时候,服务器端和客户端传输的数据有经过加密,不会被截取,比普通的http协议安全多了.下面我来介绍一下IIS6.0下SSL的配置,以实现https的访问.有详细的过程截图说明.      1.进入网站属性,选择目录安全性,然后点击服务器证书进行证书的配置: 2.创建证书,大家到这里申请免费证书,点击继续去申请. https://testca.netca.net/apply_srv/srv_root.asp 现在不好用了 3.填写完服务器的基本信息之后,然后输入C盘下cer

certbot在Centos7上配置合法签名证书,实现nginx的https访问

咖菲猫-李常明笔记 公司因之前使用的openssh创建的自签名证书,有一个弊端,就是在某些客户端上不能使用此证书,无法使用https连接,所以,研究了一下certbot 做签名证书! certbot的官网地址: https://certbot.eff.org/ 1.制作证书前的准备: 你需要有一个公网地址,并绑定合法域名 2.开始制作: (1).下载Certbot客户端: wget https://dl.eff.org/certbot-auto (2).下载后,进入下载的目录,添加执行权限 ch

nginx配置ssl证书实现https访问

一,环境说明 服务器系统:centos7.2 服务器IP地址:4xxxx 域名:bjubi.com 二,域名解析到服务器 在阿里云控制台-产品与服务-云解析DNS-找到需要解析的域名点"解析",进入解析页面后选择[添加解析]按钮会弹出如下页面: 主机记录这里选择@,记录值就是服务器ip地址,确认. 三,申请ca证书 在阿里云控制台-产品与服务-安全(云盾)-CA证书服务(数据安全),点击购买证书, 选择"免费版DV SSL",点击立即购买: 然后点去支付: 最后确认

Nginx+Tomcat服务器环境中配置https访问

一.Nginx + https + 免费SSL证书配置指南 生成证书 $ cd /usr/local/nginx/conf$ openssl genrsa -des3 -out server.key 1024$ openssl req -new -key server.key -out server.csr$ cp server.key server.key.org$ openssl rsa -in server.key.org -out server.key$ openssl x509 -re

Nginx实现ssl一级、二级域名证书部署并用https访问代理转发服务器

1.  规划 域名 解析IP Nginx代理 htpps://www.devcult.com 47.88.10.155   htpps://auto.devcult.com 47.88.10.155 https://www.automa.com htpps://www.automa.com 103.200.200.203   本次实验用了2个一级域名,1个二级域名,2个ip地址:实现功能如上图所示,要求全部使用https,并且一级域名实现自动补全www. 2. 前提准备 47.88.10.155

https访问如何生成本地证书

首先是HTTPS,我们知道使用HTTPS是需要证书的,所以接下来我们便制作一个证书. 1.使用JDK自带的工具keytool keytool -genkey -alias caskeystore -keypass 123456 -keyalg RSA -keystore thekeystore 2.导出数字证书 keytool -export -alias caskeystore -keystore thekeystore -rfc -file cas.crt 输入先前的密钥库口令,然后在当前目

nginx 自建证书以https 访问

1.生成自签名ssl证书 mkdir /ssl创建个文件夹放ssl证书openssl genrsa -des3 -out domain.key 1024#生成RSA密钥(过程需要设置一个密码,记住这个密码)openssl rsa -in ylc520.key -out ylc520_nopass.key#拷贝一个不需要输入密码的密钥文件openssl req -new -key domain.key -out domain.csr#生成一个证书请求这里会提示输入国家,地区组织,email等信息.

Tomcat创建HTTPS访问,java访问https

一 https和ssL HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL. 它是一个URI scheme(抽象标识符体系),句法类同http:体系.用于安全的HTTP数据传输.https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层