使用阿里雲負載均衡遭遇的http重定向https的問題

昨天解決了在阿里雲負載均衡上部署https證書的問題(詳見一個空行引發的阿里雲負載均衡上部署https證書的問題),並完成了部署,負載均衡的監聽配置是這樣的:html

用戶與負載均衡之間走https協議,負載均衡與後端服務器之間走http協議,這樣的好處之一是後端服務器不用一臺臺安裝證書了。web

今天早上準備實現當用戶以http訪問站點時自動跳轉爲https訪問,因而想固然地在後端web服務器中添加了一條以下的URL重寫規則(IIS URL Rewrite Module):後端

<rewrite>
    <rules>
        <rule name="redirect_http_to_https" stopProcessing="true">
            <match url="^$" />
            <conditions>
                <add input="{HTTPS}" pattern="^OFF$" />
                <add input="{REMOTE_ADDR}" pattern="^127.0.0.1$" negate="true" />
            </conditions>
            <action type="Redirect" url="https://{HTTP_HOST}/" redirectType="Temporary" />
        </rule>
    </rules>
</rewrite>

結果http的確跳轉爲https,可是直接以https訪問,Chrome瀏覽器卻出現「Redirect too many times」的錯誤,https訪問居然也會跳轉,怎麼回事?瀏覽器

停下來一想,立馬恍然大悟:本身早上還沒睡醒,忘了負載均衡與後端服務器之間始終走的是http協議,無論用戶是http訪問仍是https訪問,後端服務器收到的都是http請求,在後端服務器上根本區分不出用戶用的是http仍是https,根本沒法經過上面的URL重寫實現。服務器

向阿里雲反饋這個狀況,從客服那獲得的一個解決方法是在後端服務器上也部署https證書,讓負載均衡與後端服務器之間也走https協議。app

在衆多後端服務器上一臺臺部署證書,好麻煩;僅僅爲了重定向而讓負載均衡與後端服務器的通訊協議由http改成https,好浪費。最經濟環保的解決方法是負載均衡直接支持URL重寫,我只需在負載均衡控制檯添加一條URL重寫規則。已經向阿里雲提出了建議,但願能儘早實現。負載均衡

更新:後來阿里雲實現了:「經過X-Forwarded-Proto頭字段獲取SLB的監聽協議」ide

在ASP.NET Core中的實現代碼以下:post

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);
            }
        }            
    }       
}
public class Startup { public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { var rewriteOptions = new RewriteOptions(); rewriteOptions.Rules.Add(new RedirectToProxiedHttpsRule()); app.UseRewriter(rewriteOptions); } }
相關文章
相關標籤/搜索