概述

上文提到3.1版本默认没有使用Hsts,但是使用了这个中间件。看名字就很好理解,https跳转,顾名思义,就是跳转到

https地址。

使用场景,当用户使用http访问网站时,自动跳转到https地址。这样更加安全,不需要用户特意输入https://协议。

具体做了些我们一起来看看。

  app.UseHttpsRedirection();

使用方法

跟Hsts一样,HttpsRedirection默认是不需要注入的,除非你需要修改默认配置。

services.AddHttpsRedirection(config =>
{
//https地址的端口号,默认null
config.HttpsPort = 12345; //跳转响应的状态码,默认307
config.RedirectStatusCode = 302;
});

直接使用中间件即可

 app.UseHttpsRedirection();

源码解析

源代码很简单,只有两个类:HttpsRedirectionOptions配置类,HttpsRedirectionMiddleware中间件

HttpsRedirectionOptions就只有两个配置项

  /// <summary>
/// Options for the HttpsRedirection middleware
/// </summary>
public class HttpsRedirectionOptions
{
/// <summary>
/// The status code used for the redirect response. The default is 307.
/// </summary>
public int RedirectStatusCode { get; set; } = StatusCodes.Status307TemporaryRedirect; /// <summary>
/// The HTTPS port to be added to the redirected URL.
/// </summary>
/// <remarks>
/// If the HttpsPort is not set, we will try to get the HttpsPort from the following:
/// 1. HTTPS_PORT environment variable
/// 2. IServerAddressesFeature
/// If that fails then the middleware will log a warning and turn off.
/// </remarks>
public int? HttpsPort { get; set; }
}

重点看下中间件做了些什么。代码量很少,大体是这些逻辑。

  • 如果请求是Https,跳过本中间件
  • 中间件会依次尝试从这三个地方取端口号:HttpsRedirectionOptions的配置,HttpsRedirectionOptions,HTTPS_PORT环境变量或配置,IServerAddressesFeature(如果Webhost上绑定了https地址,本中间件能够解析出来端口号)。
  • 如果没有解析出来https的端口号,则跳过本中间件。
  • 如果能够解析出来https端口号,则拼接出来https地址,返回307跳转响应报文(或者配置的其他状态码)。

注:3.1同时支持HTTPS_PORT和ANCM_HTTPS_PORT这两个环境变量。

https://docs.microsoft.com/en-us/dotnet/core/compatibility/2.2-3.0

public class HttpsRedirectionMiddleware
{
private const int PortNotFound = -1; private readonly RequestDelegate _next;
private readonly Lazy<int> _httpsPort;
private readonly int _statusCode; private readonly IServerAddressesFeature _serverAddressesFeature;
private readonly IConfiguration _config;
private readonly ILogger _logger; /// <summary>
/// Initializes the HttpsRedirectionMiddleware
/// </summary>
/// <param name="next"></param>
/// <param name="options"></param>
/// <param name="config"></param>
/// <param name="loggerFactory"></param>
public HttpsRedirectionMiddleware(RequestDelegate next, IOptions<HttpsRedirectionOptions> options, IConfiguration config, ILoggerFactory loggerFactory) {
_next = next ?? throw new ArgumentNullException(nameof(next));
_config = config ?? throw new ArgumentNullException(nameof(config)); if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
var httpsRedirectionOptions = options.Value;
if (httpsRedirectionOptions.HttpsPort.HasValue)
{
_httpsPort = new Lazy<int>(() => httpsRedirectionOptions.HttpsPort.Value);
}
else
{
_httpsPort = new Lazy<int>(TryGetHttpsPort);
}
_statusCode = httpsRedirectionOptions.RedirectStatusCode;
_logger = loggerFactory.CreateLogger<HttpsRedirectionMiddleware>();
} /// <summary>
/// Initializes the HttpsRedirectionMiddleware
/// </summary>
/// <param name="next"></param>
/// <param name="options"></param>
/// <param name="config"></param>
/// <param name="loggerFactory"></param>
/// <param name="serverAddressesFeature">The</param>
public HttpsRedirectionMiddleware(RequestDelegate next, IOptions<HttpsRedirectionOptions> options, IConfiguration config, ILoggerFactory loggerFactory,
IServerAddressesFeature serverAddressesFeature)
: this(next, options, config, loggerFactory)
{
_serverAddressesFeature = serverAddressesFeature ?? throw new ArgumentNullException(nameof(serverAddressesFeature));
} /// <summary>
/// Invokes the HttpsRedirectionMiddleware
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public Task Invoke(HttpContext context)
{
if (context.Request.IsHttps)
{
return _next(context);
} var port = _httpsPort.Value;
if (port == PortNotFound)
{
return _next(context);
} var host = context.Request.Host;
if (port != 443)
{
host = new HostString(host.Host, port);
}
else
{
host = new HostString(host.Host);
} var request = context.Request;
var redirectUrl = UriHelper.BuildAbsolute(
"https",
host,
request.PathBase,
request.Path,
request.QueryString); context.Response.StatusCode = _statusCode;
context.Response.Headers[HeaderNames.Location] = redirectUrl; _logger.RedirectingToHttps(redirectUrl); return Task.CompletedTask;
} // Returns PortNotFound (-1) if we were unable to determine the port.
private int TryGetHttpsPort()
{
// The IServerAddressesFeature will not be ready until the middleware is Invoked,
// Order for finding the HTTPS port:
// 1. Set in the HttpsRedirectionOptions
// 2. HTTPS_PORT environment variable
// 3. IServerAddressesFeature
// 4. Fail if not sets var nullablePort = _config.GetValue<int?>("HTTPS_PORT") ?? _config.GetValue<int?>("ANCM_HTTPS_PORT");
if (nullablePort.HasValue)
{
var port = nullablePort.Value;
_logger.PortLoadedFromConfig(port);
return port;
} if (_serverAddressesFeature == null)
{
_logger.FailedToDeterminePort();
return PortNotFound;
} foreach (var address in _serverAddressesFeature.Addresses)
{
var bindingAddress = BindingAddress.Parse(address);
if (bindingAddress.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
{
// If we find multiple different https ports specified, throw
if (nullablePort.HasValue && nullablePort != bindingAddress.Port)
{
_logger.FailedMultiplePorts();
return PortNotFound;
}
else
{
nullablePort = bindingAddress.Port;
}
}
} if (nullablePort.HasValue)
{
var port = nullablePort.Value;
_logger.PortFromServer(port);
return port;
} _logger.FailedToDeterminePort();
return PortNotFound;
}
}

OK,完成了。

AspNetCore3.1_Middleware源码解析_3_HttpsRedirection的更多相关文章

  1. AspNetCore3.1_Secutiry源码解析_4_Authentication_JwtBear

    title: "AspNetCore3.1_Secutiry源码解析_4_Authentication_JwtBear" date: 2020-03-22T16:29:29+08: ...

  2. AspNetCore3.1_Secutiry源码解析_1_目录

    文章目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心项目 AspNetCore3.1_ ...

  3. AspNetCore3.1_Secutiry源码解析_2_Authentication_核心对象

    系列文章目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心项目 AspNetCore3. ...

  4. AspNetCore3.1_Secutiry源码解析_3_Authentication_Cookies

    系列文章目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心流程 AspNetCore3. ...

  5. AspNetCore3.1_Secutiry源码解析_5_Authentication_OAuth

    title: "AspNetCore3.1_Secutiry源码解析_5_Authentication_OAuth" date: 2020-03-24T23:27:45+08:00 ...

  6. AspNetCore3.1_Secutiry源码解析_6_Authentication_OpenIdConnect

    title: "AspNetCore3.1_Secutiry源码解析_6_Authentication_OpenIdConnect" date: 2020-03-25T21:33: ...

  7. AspNetCore3.1_Secutiry源码解析_8_Authorization_授权框架

    目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心流程 AspNetCore3.1_Se ...

  8. AspNetCore3.1源码解析_2_Hsts中间件

    title: "AspNetCore3.1源码解析_2_Hsts中间件" date: 2020-03-16T12:40:46+08:00 draft: false --- 概述 在 ...

  9. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

随机推荐

  1. 四、RabbitMQ Exchange类型

    RabbitMQ整体上是一个生产者与消费者模型,主要负责接收.存储和转发消息.可以把消息传递的过程想象成:当你将一个包裹送到邮局,邮局会暂存并最终将邮件通过邮递员送到收件人的手上,RabbitMQ就好 ...

  2. Mysql存储过程简单应用

    因为很久没写过存储过程了,语法也不记得了,靠百度后,解决了当前问题,这里就简单记录一下. CREATE PROCEDURE pro1() BEGIN DECLARE i int; DECLARE db ...

  3. C# for循环提升效率的写法

    ,,,,,}; ,iLen=arr.Length;i<iLen;i++) //必须是显示申明,不能var { ........... }

  4. 20180110labview串口传输实时显示相关内容

    下一步:1.在原有文件不变的基础上,输出实时波形文件,完整的4pmt4ld,并将对应的源探布配通道编号显示在面板上,对应的通道数据索引输出.2.在一次测量OK的那个文件里用while指定字节读取,注意 ...

  5. devexpress设置选中行

    版本2009.3 gvTagInfo.FocusedRowHandle = k; ;   //有效  gvTagInfo.FocusedRowHandle = k;              //这种 ...

  6. Spring学习笔记(七)模拟实际开发过程的调用过程XML版-Setter方式注入

    模拟实际开发过程的调用过程XML版-Setter方式注入 源码获取github [TOC] 1.项目结构 2.jar包跟上个一样 3.重写set方法 UserServiceImpl.java 1234 ...

  7. git push 时不用每次都输入密码的方法

    在本地克隆下来的git仓库中找到 .git 目录 (.git 目录是隐藏文件夹 在组织->文件夹和搜索选项-> 查看选项卡 -> 隐藏文件和文件夹 -> 显示隐藏的文件.文件夹 ...

  8. LeetCode#476 Number Complement - in Swift

    Given a positive integer, output its complement number. The complement strategy is to flip the bits ...

  9. 11--PHP中的类和对象

    PHP类和对象 类是面向对象程序设计的基本概念,通俗的理解类就是对现实中某一个种类的东西的抽象, 比如汽车可以抽象为一个类,汽车拥有名字.轮胎.速度.重量等属性,可以有换挡.前进.后退等操作方法. 通 ...

  10. C++走向远洋——54(项目一2、分数类的重载、取倒数)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...