AspNetCore3.1源码解析_2_Hsts中间件
概述
在DotNetCore2.2版本中,当你新增一个WebAPI项目,Startup.cs文件中,会有这么一行代码(3.1版本默认没有使用该中间件)。
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
这段代码,翻译一下就是开发环境使用开发异常页面,其他环境使用Hsts中间件。这个Hsts中间件是个什么东西呢,今天来看一看。
HSTS是什么
HTTP严格传输安全协议(英语:HTTP Strict Transport Security,简称:HSTS)。
简单描述一下协议内容,就是出于安全考虑,强制客户端使用https与服务端连接。
为什么要这么做呢,比较学术和系统的论述自行查看下面的链接。我这里举个通俗的栗子。
首先我们知道http是不安全的,而https是安全的,它能保障你访问的A网站就是A,而不是什么其他的野鸡。
某一天,你去逛淘宝,你往chrome地址栏敲 taobao.com,正常情况下岁月安好,什么问题都没有。假如,这时候你接入的是公共免费wifi,而这背后有人搞鬼,他可以将你跳转到一个跟taobao一模一样的网站 (怎么做到的?比如修改你的host文件,将taobao域名指向他自己搭建的假taobao网站ip),浏览器并不知道taobao需要使用https访问,所以无法保护你,你的钱就在你的鼠标点击下,跟随着一个个http请求流入到了黑客的账户。
那要怎么办呢,不上公共wifi行不行,行,但是防不胜防,不是根本的办法。 那我们告诉浏览器taobao需要用https访问行不行,听起来不错,那怎么告诉呢,我们来搞个协议,这个协议就是HSTS。
一句话描述HTST:当你首次使用https访问了taobao成功后,taobao会返回Strict-Transport-Security头,表明我这个网站需要使用https访问,浏览器记录下这个信息,以后taobao的请求都会使用https,因此堵住了上面案例的安全漏洞。
https://baike.baidu.com/item/HTTP严格传输安全协议/16018283?fromtitle=HSTS&fromid=8665782&fr=aladdin
https://developer.mozilla.org/zh-CN/docs/Security/HTTP_Strict_Transport_Security
HSTS中间件的使用
通常,我们不需要写Hsts的注入代码,因为它没有任何需要注入的服务。除非你需要修改它的默认配置。
services.AddHsts(config =>
{
//是否包含子域名,默认false
config.IncludeSubDomains = true;
//有效时长,默认30天
config.MaxAge = TimeSpan.FromDays(365);
});
然后,使用中间件即可。
app.UseHsts();
注意:Hsts协议只对https站点有效,如果你的站点是http的,不会报错也不会生效,使用Hsts的代码可以删掉
源码解析
Hsts的源代码比较简单,只有两个类:HstsOptions配置类和HstsMiddleware中间件。
我们先看看HstsOptions,可以看到就是一个普通配置类,定义了默认时长是30天,然后IncludeSubDomains和Preload都是默认false,然后设置ExcludedHosts,排除了本地地址。
/// <summary>
/// Options for the Hsts Middleware
/// </summary>
public class HstsOptions
{
/// <summary>
/// Sets the max-age parameter of the Strict-Transport-Security header.
/// </summary>
/// <remarks>
/// Max-age is required; defaults to 30 days.
/// See: https://tools.ietf.org/html/rfc6797#section-6.1.1
/// </remarks>
public TimeSpan MaxAge { get; set; } = TimeSpan.FromDays(30);
/// <summary>
/// Enables includeSubDomain parameter of the Strict-Transport-Security header.
/// </summary>
/// <remarks>
/// See: https://tools.ietf.org/html/rfc6797#section-6.1.2
/// </remarks>
public bool IncludeSubDomains { get; set; }
/// <summary>
/// Sets the preload parameter of the Strict-Transport-Security header.
/// </summary>
/// <remarks>
/// Preload is not part of the RFC specification, but is supported by web browsers
/// to preload HSTS sites on fresh install. See https://hstspreload.org/.
/// </remarks>
public bool Preload { get; set; }
/// <summary>
/// A list of host names that will not add the HSTS header.
/// </summary>
public IList<string> ExcludedHosts { get; } = new List<string>
{
"localhost",
"127.0.0.1", // ipv4
"[::1]" // ipv6
};
然后我们看看中间件的代码,也十分简单。首先判断是不是https请求,不是的话直接跳过本中间件;然后判断是否在除外域名配置中,是的话也跳过。然后就是根据HstsOptions的配置拼装内容,然后写入http的响应头中。
public class HstsMiddleware
{
private const string IncludeSubDomains = "; includeSubDomains";
private const string Preload = "; preload";
private readonly RequestDelegate _next;
private readonly StringValues _strictTransportSecurityValue;
private readonly IList<string> _excludedHosts;
private readonly ILogger _logger;
/// <summary>
/// Initialize the HSTS middleware.
/// </summary>
/// <param name="next"></param>
/// <param name="options"></param>
/// <param name="loggerFactory"></param>
public HstsMiddleware(RequestDelegate next, IOptions<HstsOptions> options, ILoggerFactory loggerFactory)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
_next = next ?? throw new ArgumentNullException(nameof(next));
var hstsOptions = options.Value;
var maxAge = Convert.ToInt64(Math.Floor(hstsOptions.MaxAge.TotalSeconds))
.ToString(CultureInfo.InvariantCulture);
var includeSubdomains = hstsOptions.IncludeSubDomains ? IncludeSubDomains : StringSegment.Empty;
var preload = hstsOptions.Preload ? Preload : StringSegment.Empty;
_strictTransportSecurityValue = new StringValues($"max-age={maxAge}{includeSubdomains}{preload}");
_excludedHosts = hstsOptions.ExcludedHosts;
_logger = loggerFactory.CreateLogger<HstsMiddleware>();
}
/// <summary>
/// Initialize the HSTS middleware.
/// </summary>
/// <param name="next"></param>
/// <param name="options"></param>
public HstsMiddleware(RequestDelegate next, IOptions<HstsOptions> options)
: this(next, options, NullLoggerFactory.Instance) { }
/// <summary>
/// Invoke the middleware.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/>.</param>
/// <returns></returns>
public Task Invoke(HttpContext context)
{
if (!context.Request.IsHttps)
{
_logger.SkippingInsecure();
return _next(context);
}
if (IsHostExcluded(context.Request.Host.Host))
{
_logger.SkippingExcludedHost(context.Request.Host.Host);
return _next(context);
}
context.Response.Headers[HeaderNames.StrictTransportSecurity] = _strictTransportSecurityValue;
_logger.AddingHstsHeader();
return _next(context);
}
private bool IsHostExcluded(string host)
{
if (_excludedHosts == null)
{
return false;
}
for (var i = 0; i < _excludedHosts.Count; i++)
{
if (string.Equals(host, _excludedHosts[i], StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
AspNetCore3.1源码解析_2_Hsts中间件的更多相关文章
- AspNetCore3.1_Secutiry源码解析_1_目录
文章目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心项目 AspNetCore3.1_ ...
- AspNetCore3.1_Secutiry源码解析_2_Authentication_核心对象
系列文章目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心项目 AspNetCore3. ...
- AspNetCore3.1_Secutiry源码解析_5_Authentication_OAuth
title: "AspNetCore3.1_Secutiry源码解析_5_Authentication_OAuth" date: 2020-03-24T23:27:45+08:00 ...
- AspNetCore3.1_Secutiry源码解析_8_Authorization_授权框架
目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心流程 AspNetCore3.1_Se ...
- AspNetCore3.1_Secutiry源码解析_3_Authentication_Cookies
系列文章目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心流程 AspNetCore3. ...
- AspNetCore3.1_Secutiry源码解析_4_Authentication_JwtBear
title: "AspNetCore3.1_Secutiry源码解析_4_Authentication_JwtBear" date: 2020-03-22T16:29:29+08: ...
- AspNetCore3.1_Secutiry源码解析_6_Authentication_OpenIdConnect
title: "AspNetCore3.1_Secutiry源码解析_6_Authentication_OpenIdConnect" date: 2020-03-25T21:33: ...
- 【原创】express3.4.8源码解析之中间件
前言 注意:旧文章转成markdown格式. 中间件(middleware)的概念来自于TJ的connect库,express就是建立在connect之上. 就如同connect的意思是 连接 一样, ...
- AspNetCore源码解析_1_CORS中间件
概述 什么是跨域 在前后端分离开发方式中,跨域是我们经常会遇到的问题.所谓的跨域,就是处于安全考虑,A域名向B域名发出Ajax请求,浏览器会拒绝,抛出类似下图的错误. JSONP JSONP不是标准跨 ...
随机推荐
- Centos防火墙开启端口
linux系统对外开放80.8080等端口,防火墙设置 我们很多时候在liunx系统上安装了web服务应用后(如tomcat.apache等),需要让其它电脑能访问到该应用,而Linux系统(cent ...
- mysql报错2003 ,can't connect to mysql server on “localhost”
我在安装成功后启动MySQL服务时,服务启动不了,提示:MySQL服务无法启动 服务没有报告任何错误 请键入NET HELPMSG 3534 以获得更多帮助,如下: 解决方案:安装好MySQL后 ...
- 在Docker内安装jenkins运行和基础配置
这里是在linux环境下安装docker之后,在doucer内安装jenkins --------------------docker 安装 jenkins---------------------- ...
- Ionic3学习笔记(六)存储之使用 SQLite
本文为原创文章,转载请标明出处 目录 安装 CURD操作 1. 安装 命令行输入 ionic cordova plugin add cordova-sqlite-storage npm install ...
- Web自动化测试平台设计与落地-概览
引言 自动化金字塔-灵魂手绘版 关于Web自动化测试,投入产出比是一个绕不开的话题,对于走到2017年的测试人,这时候可能已经有很多人会想到著名的自动化测试金字塔.它形象地展示了Mike Cohn对自 ...
- spring入门(14)
AOP是一个新的专题,基础部分主要是入门 后续的五.六.七都属于AOP专题: 所以有必要对这三章要学什么有个全局的认识. 1 概要 1 什么是AOP及实现方式 介绍了AOP的用途,以及大致的实现方案 ...
- zabbix监控mysql数据库信息脚本
---恢复内容开始--- 在/usr/local/zabbix/etc/zabbix_agentd.conf增加 # 获取mysql性能指标 UserParameter=mysql.status[*] ...
- LeetCode~报数(简单)
报数(简单) 题目描述: 报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数.其前五项如下: 1 11 21 1211 111221 1 被读作 "one 1" ( ...
- STL容器的使用
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- Sublime Text3 旧版本下载以及破解激活方式
前言 当前Sublime Text3 出到了32**版本,以前直接输入激活码的方法已经不能使用. 而官网又不提供旧版本的下载链接,因此在此分享旧版本下载方式以及激活方式. 下载方法 通过下面这个链接下 ...