合格的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 位址接收請求。
安裝 .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
歡迎關注我的原創技術、職場公衆号, 加好友談天說地,一起進化