• 白话文解读HTTPS原理, 结合.NET Core聊一聊HTTPS应用方式


           合格的web后端程序员,除搬砖技能,还必须会给各种web服务器配置Https,本文结合ASP.NET Core部署模型聊一聊启用Https的方式。

    温故知新

    目前常见的Http请求明文传输,请求可能被篡改,访问的站点可能被伪造。

    HTTPS是HTTP加上TLS/SSL协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。

    HTTPS是应用层协议

    注意,HTTPS是与DNS平级的应用层协议, 一个常见HTTPS请求的过程:

     由DNS解析出IP地址----->  浏览器向服务器ip地址发起请求----> 服务器向浏览器下发证书(该证书有公钥,并绑定了域名)-----> 浏览器验证证书---->....

    HTTPS 流程解读

    ① 传输密钥是对称密钥,用于双方对传输数据的加解密

    ② 怎么在传输之前确立传输密钥呢?

     答:针对普遍的多客户端访问受信web服务器的场景, 提出非对称密钥(公钥下发给客户端,私钥存于web服务器),双方能互相加解密,说明中间数据(传输密钥)没被篡改。

    ③ 再抛出疑问,客户端如何认定下发的公钥是目标web服务器的公钥?又如何确定公钥下发过程没被截取篡改?

     答:追溯到握手阶段的证书验证过程,浏览器从证书提取(证书颁发机构,证书绑定的域名,证书签名,证书有效期),

      浏览器先验证证书绑定的域名是否与目标域名匹配;浏览器内置证书颁发机构认定该证书是其有效下发;通过签名认定该证书没被篡改。

    ④ 所以浏览器内置的证书机构(根证书)的权威性相当重要, 浏览器中毒或劣质浏览器可能携带 非法的根证书。

     如果面向面试记忆Https原理,恐怕有些难度,所以个人用一种 【鸡生蛋还是蛋生鸡】的方式向上追溯流程, 方便大家知其然更知其所以然 

    ⑤ 是不是只有CA机构才能签发证书 ?  

     不是的,服务器上存储的证书和公钥,只要是匹配的就可以下发;由浏览器决定是否信任证书。

      所以在测试和开发阶段,通常在服务器上申请 自签名证书,浏览器会提示你证书无效,但是你可手动忽略,或添加到信任列表。

    下面演示对ASP.NET Core程序两种最常见部署模型强制应用HTTPS.

    常规反向代理模型

     由nginx反向代理请求到后端https://receiver.server, nginx上添加HTTPS证书, 并强制浏览器使用 HTTPS。

    worker_processes 4;
    events { worker_connections 1024; }
    http {
        sendfile on;
        upstream receiver_server {
            server receiver:80;
        }
        server {
            listen 80;
            listen [::]:80;
            server_name  eqid.******.com;
            return 301 https://$host$request_uri;
        }
    
        server {
            listen       443 ssl;
            listen       [::]:443 ssl;
            ssl          on;
            server_name  eqid.******.com;
    
            ssl_certificate         /conf.crt/live/******.com.crt;
            ssl_certificate_key     /conf.crt/live/******.com.key;
            location / {
                proxy_pass         http://receiver_server;
                proxy_http_version 1.1;
                proxy_set_header   Upgrade $http_upgrade;
                proxy_set_header   Connection keep-alive;
                proxy_redirect     off;
                proxy_set_header   Host $host;
                proxy_cache_bypass $http_upgrade;
                proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header   X-Forwarded-Proto $scheme;
            }
        }
    }

    黄色背景行显示: nginx对http:80 请求返回301(重定向,Moved Permanently), 要求浏览器使用Https发起请求。

    绿色背景行显示: nginx对此次 https请求,在协商阶段会下发ssl_certificate证书, 会使用 ssl_certificate_key 私钥进行非对称解密。

    dotnet.exe自宿模型

     Kestrel用作边缘(面向Internet)Web服务器, 这个部署模型不常见,但依旧存在。

    我们利用 Visual Studio 2019项目模板构建 ASP.NetCore项目--- 勾选HTTPS支持, 会默认添加Https支持;

    • app.UseHttpsRedirection()   要求浏览器的Http请求  重定向使用 HTTPS协议
    • app.UseHsts()
    HSTS(HTTP Strict Transport Protocol)的作用是强制浏览器使用HTTPS与服务器创建连接,避免原有的301重定向Https时可能发生中间人劫持
    服务器开启HSTS的方法是,当客户端通过HTTPS发出请求时,在服务器返回的超文本传输协议响应头中包含Strict-Transport-Security字段。非加密传输时设置的HSTS字段无效。

      它告诉浏览器为特定的主机头和特定的时间范围缓存证书。

    开发证书

    VS模板构建的web会使用dotnet cli 提供的开发证书在https://localhost:5001 地址接收请求。

    关于开发证书, 可倒腾 dotnet dev-certs https --help 命令:

    dotnet dev-certs https --clean  清除证书,启动程序会报 System.InvalidOperationException:“Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date. To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'.

    dotnet dev-certs https -t  信任证书,会弹窗提示安装名为localhost的根证书

         - 否,web能正常启动,浏览器Https请求能获取证书,但会警示 ▲不安全 (浏览器不信任localhost根证书,证书无效)

        -  是,web正常启动,浏览器发起的Https请求,显示正常的显示♎ 图标

    在Windows上,最安全方式是使用certificate store来注册已认证的HTTPS,但是有时候希望在程序内绑定证书+私钥, 这样便于在不同平台上部署。

    文件证书

    ASP.NET Core支持使用硬盘上文件证书来建立Https连接(这在linux上很常见)。

    以下代码允许Kestrel 传入文件证书和私钥,并建立Https连接。

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseKestrel(options =>
            {
                options.Listen(IPAddress.Loopback, 5000);
                options.Listen(IPAddress.Loopback, 5001, listenOptions =>
                {
                    listenOptions.UseHttps("certificate.pfx", "topsecret");
                });
            })
            .UseStartup<Startup>();

    务必确保不要将私钥存储在配置文件中:在开发模式,可使用 user secrets 存储此类密钥;在生产模式,可考虑Azure Key Vault或环境变量。

    完整密钥分离请参考: https://www.cnblogs.com/JulianHuang/p/11462607.html

    编程允许HttpClient发起不安全的请求

    有时候你会使用HttpClient等客户端去请求 受信HTTPS站点, 但是因为某些原因(自签名证书,证书过期), 下发的证书无效 (这个时候浏览器会提示,你可选择忽略,或者手动添加到受信列表继续请求),

    但是编程方式的HttpClinet 会立刻终止请求。

    给栗子:

    使用默认的HttpClient BaseAddress=https://127.0.0.1:5001,访问ASP.NET Core 默认站点https://localhost:5001,  会出现:

    这个时候你可考虑重写HttpClient ServerCertificateCustomValidationCallback属性 忽略无效证书报错。

     [Route("test")]
            public async Task<string> Get()
            {
                var client = new HttpClient(new HttpClientHandler()
                {
                    AllowAutoRedirect = true,
                    ServerCertificateCustomValidationCallback = (x1, x2, x3, x4) => true
                });
                var resp = await  client.GetAsync("https://127.0.0.1:5001");
                return await resp.Content.ReadAsStringAsync();
            }

    总结 

    希望本文有助于您大致了解 HTTPS的协议原理,常见的HTTPS的应用方式,

    结合.NETCore 说明开发证书 和 文件证书的使用方式, 最后指出允许HttpClient发起不安全请求的方式。

     

  • 相关阅读:
    个人技术博客(α)------javaweb的学习路程
    使用github客户端上传文件(瓜皮教程)
    软件工程实践 : 团队项目(第三次作业) 需求规格说明书
    软件工程实践 · 团队项目(第二次作业)
    软件工程实践:结对作业(第二次作业)
    软件工程实践:结对作业(第一次作业)
    软件工程实践 · 团队项目(第一次作业)
    班级连接
    软件工程 第二次作业(改)
    Shader Forge 刀光溶解
  • 原文地址:https://www.cnblogs.com/JulianHuang/p/11858800.html
Copyright © 2020-2023  润新知