asp.net core中負載平衡情境下http重新導向https的問題

來源:互聯網
上載者:User

標籤:負載   netcore   des   sof   sch   定向   das   oid   hub   

上周欣喜地發現,微軟官方終於針對 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);

asp.net core中負載平衡情境下http重新導向https的問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.