當前位置:
首頁 > 知識 > asp.net core中負載均衡場景下http重定向https的問題

asp.net core中負載均衡場景下http重定向https的問題

上周欣喜地發現,微軟官方終於針對 asp.net core 在使用負載均衡的情況下從 http 強制重定向至 https 的問題提供了解決方法。

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedProto
});

var options = new RewriteOptions
.AddRedirectToHttpsPermanent;
app.UseRewriter(options);

但實際使用之後,欣喜變成了失望 —— 微軟對這個問題的認識角度和我們不一樣,造成這個方法對我們不適用,不得不繼續使用我們的土方法。

為什麼會這樣?請看下面的分解。

AddRedirectToHttpsPermanent 早就在 BasicMiddleware的RedirectToHttpsRule中實現了,它的邏輯很簡單 —— 判斷當前請求是否是https,如果不是就進行重定向。

if (!context.HttpContext.Request.IsHttps)
{
//...
}

這個直接了當的判斷在使用負載均衡的場景下不僅不會發揮應有的作用,而且會產生致命的副作用 —— 讓請求進入重定向死循環(ERR_TOO_MANY_REDIRECTS)。因為不管客戶端的請求是 http 還是 https ,負載均衡與後端伺服器之間始終是 http(當然你可以用https,但那是吃飽了撐著還浪費糧食)。如果負載均衡不額外提供這個信息,在後端伺服器的眼裡始終只有 http 沒有 https ,http 重定向 https 根本無法實現。

從負載均衡的角度,為了解決這個問題,通常會通過一個另外的專用的請求頭抓發這個信息,它的名字叫"X-Forwarded-Proto"。

從 asp.net core 的角度,要解決這個問題,需要彌補 Request.IsHttps 與 X-Forwarded-Proto 之間的鴻溝。於是微軟實現了上面的 app.UseForwardedHeaders ,實際是由 ForwardedHeadersMiddleware完成這個任務 —— 根據 X-Forwarded-Proto 設置 Scheme(Request.IsHttps 就是基於 Scheme 進行判斷的)。

if (checkProto && i < forwardedProto.Length) { set.Scheme = forwardedProto[forwardedProto.Length - i - 1]; }

到此為止,微軟完美地解決了這個問題,RedirectToHttpsRule 不用修改1行代碼。

但是在實際使用時,我們發現一個大問題,大到我們必須棄用這個看似完美的解決方法。

微軟解決 http to https 問題的思路是這樣:只要請求不是 https 的,就強制跳轉到 https(這個沒問題),其他一概不管,不管這個請求是不是來自負載均衡轉發的(這個不夠貼心)。

而我們要解決的問題是:只有在負載均衡轉發的原始請求是 http 的情況下,才強制跳轉至 https 。比如在伺服器本機訪問,比如來自其他docker容器的訪問,如果這也跳轉,那每台伺服器(或者docker容器)都要部署https證書,多麻煩。

一個是只要不是 https ,就跳轉;一個是只有是轉發的 http ,才跳轉。 就是因為這個對問題理解的差異,我們不得不放棄採用微軟的官方解決方法,繼續使用我們不太優雅的土方法。

RedirectToProxiedHttpsRule

public class RedirectToProxiedHttpsRule : RedirectToHttpsRule
{
public RedirectToProxiedHttpsRule
{
base.StatusCode = StatusCodes.Status301MovedPermanently;
base.SSLPort = null;
}

public override void ApplyRule(RewriteContext context)
{
var key = "X-Forwarded-Proto";
var request = context.HttpContext.Request;
if (request.Headers.ContainsKey(key))
{
if (request.Headers[key].FirstOrDefault == "http")
{
base.ApplyRule(context);
}
}
}
}

RewriteOptionsExtensions

public static class RewriteOptionsExtensions
{
public static RewriteOptions AddRedirectForwardedHttpToHttps(this RewriteOptions options)
{
options.Rules.Add(new RedirectToProxiedHttpsRule);
return options;
}
}

在 Startup 中使用

var options = new RewriteOptions
.AddRedirectForwardedHttpToHttps;
app.UseRewriter(options);

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

Python:一篇文章掌握Numpy的基本用法
UIButton圖片文字控制項位置自定義
Java集合-LinkedList

TAG:科技優家 |

您可能感興趣

Https payload與C2重定向
spring+shiro+cas的整合問題之循環重定向
Nginx配置SSL實現https請求並重定向http請求的實現
Vue.js路由:route/router,重定向/別名,導航守衛,路由元信息等
雲計算怎麼學?Io重定向Redirection詳解
Servlet 網頁重定向
Google Adwords推廣鏈接自動重定向到HTTPS
linux下簡單好用的工具rinetd,實現埠映射/轉發/重定向
乾貨:Nginx伺服器中301重定向跳轉到帶www的域名方法!
Shell 輸入/輸出重定向
Linux 常用基本命令之重定向
華為 E3276 終端無法完成 LTE到WCDMA 的盲重定向切換問題分析報告
VR技術突破!英偉達、Adobe發明眼球掃視重定向行走技術
VR技術突破 英偉達、Adobe發明眼球掃視重定向行走技術
JSP 頁面重定向
PHP 重定向代碼
負載均衡學習筆記之HTTP重定向負載均衡
防禦地球計劃:NASA計劃2020年實施DART雙小行星重定向測試
JCI:重定向到骨髓可改善治療性T細胞的持久性和抗腫瘤能力
重定向行走:一眨眼的功夫,眼前的VR畫面就別掉了包