上周欣喜地发现,微软官方终于针对 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);

原文地址:http://www.cnblogs.com/dudu/p/7044923.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

asp.net core中负载均衡场景下http重定向https的问题相关推荐

  1. ASP.NET Core 中使用负载均衡时获取客户端 IP

    在使用负载均衡的情况下,通过 context.Connection.RemoteIpAddress 获取到的是负载均衡的 IP 地址,需要通过 X-Forwarded-For 请求头才能获取到客户端的 ...

  2. ASP.NET Core 中的静态文件

    1.前言 当我们创建Core项目的时候,Web根目录下会有个wwwroot文件目录,wwwroot文件目录里面默认有HTML.CSS.IMG.JavaScript等文件,而这些文件都是Core提供给客 ...

  3. ASP.NET Core中Ocelot的使用:基于服务发现的负载均衡

    本系列相关文章: <ASP.NET Core中Ocelot的使用:API网关的应用> <ASP.NET Core中Ocelot的使用:基于Spring Clound Netflix ...

  4. 大型网站演变中的负载均衡场景,netty实战pdf中文下载

    我们小伙伴们是不是经常看到网上一些集群.高可用.高并发.负载均衡等关键词,有很多种方案.以及应用场景中都有相关的介绍.今天老顾就带着大家一起看一下,一整套大型网站会有哪些负载均衡方案场景. 创业阶段 ...

  5. 如何在 ASP.NET CORE 中获取客户端 IP ?

    咨询区 eadam: 在 ASP.NET 中我可以用 Request.ServerVariables["REMOTE_ADDR"] 来获取客户端IP地址,请问在 ASP.NET C ...

  6. Api网关Kong集成Consul做服务发现及在Asp.Net Core中的使用

     1622219047536 写在前面   Api网关我们之前是用 .netcore写的 Ocelot的,使用后并没有完全达到我们的预期,花了些时间了解后觉得kong可能是个更合适的选择. 简单说下 ...

  7. Asp.Net Core 中IdentityServer4 授权中心之应用实战

    一.前言 查阅了大多数相关资料,搜索到的IdentityServer4 的应用文章大多是比较简单并且多是翻译官网的文档编写的,我这里在 Asp.Net Core 中IdentityServer4 的应 ...

  8. 探索ASP.NET Core中的IStartupFilter

    原文:Exploring IStartupFilter in ASP.NET Core 作者:Andrew Lock 译者:Lamond Lu 在本篇博客中,我将介绍一下IStartupFilter, ...

  9. .ASP NET Core中缓存问题案例

    本篇博客中,我将描述一个关于会话状态(Session State)的问题, 这个问题我已经被询问了好几次了. 问题的场景 创建一个新的ASP.NET Core应用程序 一个用户在会话状态中设置了一个字 ...

最新文章

  1. 枚举法 之Java实现凑硬币
  2. 左神算法:用栈来求解限制后的汉诺塔问题(Java版)
  3. dropbox_来自提示框:望远镜激光瞄准器,Dropbox桌面和Kindle剪辑转换
  4. JS将指定的时间戳转为UTC时间
  5. android animatorset 监听,Android源码分析--动画框架AnimatorSet
  6. 南亚三大半岛_南亚最大的维基百科聚会开始
  7. 编译lua5.3.2报错提示libreadline.so存在未定义的引用解决方法
  8. webGIS的粗浅认识(一)
  9. 手机变身电脑摄像头 Droidcam使用
  10. 华为手机便签怎样一键扫描图片转化成文字?
  11. 奔驰c260语言设置方法图解,奔驰C260L灯光使用方法 C260L灯光开关图解说明
  12. [OC学习笔记]自动引用计数
  13. linux mtd - mtdpart.c
  14. 大脑构造图与功能解析_人类大脑的生理构造及功能分区
  15. PDF转成Word或PPT后不能修改的原因和解决方法
  16. 安装与破解IntelliJ IDEA2017
  17. 展开运算符和object.assign()的区别
  18. 本地无法打开localhost或127.0.1解决方案
  19. Vue 汉字转简拼首字母大写
  20. ZZULIOJ 1180-1198结构体专题 参考代码

热门文章

  1. Mybatis-Generator(MBG)教程与Idea的MBG插件
  2. 重装系统后恢复oracle数据
  3. Linux 下用来查询安装包信息的RPM选项
  4. Windows UI风格的设计(11)
  5. 显示桌面,原来这么简单的
  6. 八款Js框架介绍及比较~转载
  7. 在 WASI 上运行 .NET 7 应用程序
  8. .NET6之MiniAPI(二十七):Metrics
  9. Avalonia跨平台入门第八篇之控件的拖放
  10. 客户要求ASP.NET Core API返回特定格式,怎么办?(续)