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 - ];
}
到此为止,微软完美地解决了这个问题,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的问题的更多相关文章
- CephRGW 在多个RGW负载均衡场景下,RGW 大文件并发分片上传功能验证
http://docs.ceph.com/docs/master/radosgw/s3/objectops/#initiate-multi-part-upload 根据分片上传的API描述,因为对同一 ...
- 使用阿里云负载均衡遭遇的http重定向https的问题
昨天解决了在阿里云负载均衡上部署https证书的问题(详见一个空行引起的阿里云负载均衡上部署https证书的问题),并完成了部署,负载均衡的监听配置是这样的: 用户与负载均衡之间走https协议,负载 ...
- ASP.NET Core 中使用负载均衡时获取客户端 IP
在使用负载均衡的情况下,通过 context.Connection.RemoteIpAddress 获取到的是负载均衡的 IP 地址,需要通过 X-Forwarded-For 请求头才能获取到客户端的 ...
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
项目开发中的一些注意事项以及技巧总结 1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...
- ASP.NET Core中显示自定义错误页面
在 ASP.NET Core 中,默认情况下当发生500或404错误时,只返回http状态码,不返回任何内容,页面一片空白. 如果在 Startup.cs 的 Configure() 中加上 app. ...
- ASP.NET Core 中的 Razor 页面介绍
标题:ASP.NET Core 中的 Razor 页面介绍 地址:https://docs.microsoft.com/zh-cn/aspnet/core/razor-pages/index?view ...
- Nginx知多少系列之(六)Linux下.NET Core项目负载均衡
目录 1.前言 2.安装 3.配置文件详解 4.工作原理 5.Linux下托管.NET Core项目 6.Linux下.NET Core项目负载均衡 7.负载均衡策略详解 8.Linux下.NET C ...
- Windows平台分布式架构实践 - 负载均衡(下)
概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效 ...
- Windows平台下利用APM来做负载均衡方案 - 负载均衡(下)
概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效 ...
随机推荐
- EXT 可选择图片列表的表单控件实现
先看一下表单效果: 点击图标,显示图标列表: 实现代码: var appform = new Ext.form.FormPanel({ id: 'appform', cardStep:0, url:A ...
- 浅谈移动端rem的用法
一 什么是rem? “font size of the root element 这是w3c的定义 也就是说是相对于根节点(html节点)的字体大小的单位. 目前主流的浏览器基本都支持rem这个单位, ...
- Hadoop化繁为简-从安装Linux到搭建集群环境
简介与环境准备 hadoop的核心是分布式文件系统HDFS以及批处理计算MapReduce.近年,随着大数据.云计算.物联网的兴起,也极大的吸引了我的兴趣,看了网上很多文章,感觉还是云里雾里,很多不必 ...
- UISement属性
.segmentedControlStyle 设置segment的显示样式. typedef NS_ENUM(NSInteger, UISegmentedControlStyle) { UISegme ...
- mysql获取当前日期的周一和周日的日期
,,date_format(curdate(),)//获取当前日期 在本周的周一 的日期 ,,date_format(curdate(),)//获取当前日期 在本周的周日 的日期
- Spring装配bean--01组件扫描和自动装配
Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系 Spring提供了三种主要的装配机制: 在XML中进行显式配置 在Java中进行显式配置 隐式的bean发现机制和自动装 ...
- vs2015c++/MFC入门知识全集/实例规范书籍视频下载孙鑫c++对话框计算器基础控件使用教程系列
VIP教程可免费看.可免费下载前部分试看教程地址:http://dwz.cn/4PcfPk免费下载地址:http://dwz.cn/mfc888 本课程目录 67章 [MFC项目开发第01天]Wind ...
- jgs--多线程和synchronized
多线程 多线程是我们开发人员经常提到的一个名词.为什么会有多线程的概念呢?我们的电脑有可能会有多个cpu(或者CPU有多个内核)这就产生了多个线程.对于单个CPU来说,由于CPU运算很快,我们在电脑上 ...
- 面向切面编程(Aop)
AOP中的概念 AOP(Aspect Orient Programming),也就是面向切面编程.可以这样理解,面向对象编程(OOP)是从静态角度考虑程序结构,面向切面编程(AOP)是从动态角度考虑程 ...
- Spring切面通知执行的顺序(Advice Order)
问题描述 如果在Spring的程序中同时定义了环绕通知(Around)和前置通知(Before)..那么,有以下问题: 1.怎么让两个切面通知都起作用 2.或者让两者切面按自己指定的顺序进行执行? 3 ...