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

到此为止,微软完美地解决了这个问题,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的问题的更多相关文章

  1. CephRGW 在多个RGW负载均衡场景下,RGW 大文件并发分片上传功能验证

    http://docs.ceph.com/docs/master/radosgw/s3/objectops/#initiate-multi-part-upload 根据分片上传的API描述,因为对同一 ...

  2. 使用阿里云负载均衡遭遇的http重定向https的问题

    昨天解决了在阿里云负载均衡上部署https证书的问题(详见一个空行引起的阿里云负载均衡上部署https证书的问题),并完成了部署,负载均衡的监听配置是这样的: 用户与负载均衡之间走https协议,负载 ...

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

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

  4. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

  5. ASP.NET Core中显示自定义错误页面

    在 ASP.NET Core 中,默认情况下当发生500或404错误时,只返回http状态码,不返回任何内容,页面一片空白. 如果在 Startup.cs 的 Configure() 中加上 app. ...

  6. ASP.NET Core 中的 Razor 页面介绍

    标题:ASP.NET Core 中的 Razor 页面介绍 地址:https://docs.microsoft.com/zh-cn/aspnet/core/razor-pages/index?view ...

  7. Nginx知多少系列之(六)Linux下.NET Core项目负载均衡

    目录 1.前言 2.安装 3.配置文件详解 4.工作原理 5.Linux下托管.NET Core项目 6.Linux下.NET Core项目负载均衡 7.负载均衡策略详解 8.Linux下.NET C ...

  8. Windows平台分布式架构实践 - 负载均衡(下)

    概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效 ...

  9. Windows平台下利用APM来做负载均衡方案 - 负载均衡(下)

    概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效 ...

随机推荐

  1. caffe:使用C++来提取任意一张图片的特征(从内存读取数据)

    0x00 关于使用C++接口来提取特征,caffe官方提供了一个extract_features.cpp的例程,但是这个文件的输入是blob数据,即使输入层使用的是ImageData,也需要在depl ...

  2. 实体类和数据表的映射异常(XXX is not mapping[ ])

    在使用SSH框架开发过程,使用hibernate框架提供的工具类实现与数据库数据交互,在执行cmd操作时,如果出现以下异常: org.hibernate.hql.ast.QuerySyntaxExce ...

  3. Android计时器 android.widget.Chronometer

    说起做定时器,大家一般会想到Timer和Executors的定时器线程池,其实用这两个做都会有问题,在停止和重新计时时你回发现无法停止或者说计时加快(加快是因为多个线程在记录同一个变量),Androi ...

  4. Lua快捷键

      快捷键 含义 ctrl + shift + L 多行编辑 ctrl + D 继续向下选中下一个相同的文本 Alt + F3 选中所有相同所选中德文本                        

  5. 来自一位工作一年多的猿的分享 ------- ioc

    这是我第一次写东西记录吧:还记得小学老师教的写文章要有"开篇 起伏 高潮...高潮 结束",反正我不会用上: 最近在研究IOC这玩意:百度了很多关于这方面的帖子:关于IOC和DI的 ...

  6. SQLyog-12.4.2版下载,SQLyog最新版下载,SQLyog官网下载,SQLyog Download

    SQLyog-12.4.2版下载,SQLyog最新版下载,SQLyog官网下载,SQLyog Download >>>>>>>>>>> ...

  7. Unity之2D Sprite Outline外轮廓效果

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Unity5.3.8f1 Unity提供了2D Object Sprite对象,但是没有提供外轮廓Outline效果的支持 ...

  8. conda 使用清华大学开源软件镜像

    conda 使用清华大学开源软件镜像 Anaconda的安装步骤不在本文的讨论中,我们主要是学习一下如何配置conda的镜像,以及一些问题的解决过程 配置镜像 在conda安装好之后,默认的镜像是官方 ...

  9. 创建发布自己的npm包

    我们基于nodejs平台上面的npm上,可以随意下载很多npm安装包.那我们如何创建自己的npm包呢?很简单,废话少说,开始做~ 开始做之前nodejs默认是要安装的,怎么安装自行百度其他教程. 首先 ...

  10. zabbix监控Elasticsearch集群

    本节以 zabbix 为例,介绍如何使用监控系统完成 Elasticsearch 的监控报警. github 上有好几个版本的 ESZabbix 仓库,都源自 Elastic 公司员工 unterge ...