白话文解读HTTPS原理, 结合.NET Core聊一聊HTTPS应用方式
合格的web后端程序员,除搬砖技能,还必须会给各种web服务器配置Https,本文结合ASP.NET Core部署模型聊一聊启用Https的方式。
温故知新
目前常见的Http请求明文传输,请求可能被篡改,访问的站点可能被伪造。
HTTPS是HTTP加上TLS/SSL协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。
HTTPS是应用层协议
注意,HTTPS是与DNS平级的应用层协议, 一个常见HTTPS请求的过程:
由DNS解析出IP地址-----> 浏览器向服务器ip地址发起请求----> 服务器向浏览器下发证书(该证书有公钥,并绑定了域名)-----> 浏览器验证证书---->....
HTTPS 流程解读

这里面千万不要忽略 申请CA证书这关键前置步骤,不然后面的推理都是无根之木。
1> 给服务器域名申请证书(域名、有效期), CA机构会返回证书 (域名、有效期、证书颁发机构、证书所有人,公钥、证书签名), 其中的证书签名是CA机构用自己的私钥对这个明文信息做的哈希, 还有一个私钥。
> 所以以后遇到签名,你就可以认为是对明文信息做哈希, 信息在传递时也是明文的, 签名、验证的目的只为证明这个信息没被篡改,值得信任。 另外你也别把证书当成什么高级的东西,就把它当成一个数据机构实体,有许多字段。
2> 浏览器用内置的CA证书的公钥验签(其实就是对证书信息再做一次哈希,看前后哈希值是不是一样), 得出证书没被篡改的结论, 也就是里面的公开信息:域名、有效期、证书颁发机构、证书所有人、证书公钥、都是值得信任的。
> 这里面技术上重要的自然是 证书公钥了。
3> 客户端拿到证书的服务器公钥,使用随机值产生会话密钥, 用公钥加密信息(会话密钥), 送到对端; 服务器用私钥解密出信息(会话密钥),
4> 后面就是使用会话密钥加密信息 通信了。
---
下面演示对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 地址接收请求。
安装 .NET Core SDK 会将 ASP.NET Core HTTPS 开发证书安装到本地用户证书存储 , 可倒腾 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发起不安全请求的方式。
本文来自博客园,作者:{有态度的马甲},转载请注明原文链接:https://www.cnblogs.com/JulianHuang/p/11858800.html
欢迎关注我的原创技术、职场公众号, 加好友谈天说地,一起进化

浙公网安备 33010602011771号