一、中间件知识

1、概念
(1).NetCore目录分析:NetCore环境下的MVC——NET5运行时之前

 

2、创建中间件示例
(1)ASP.NETCore-中间件Middleware_编写中间件_NET5
(2)ASP.NETCore-中间件Middleware_编写中间件_NET7
3、中间件与MVC中过滤器(Filter)、拦截器(Interceptor)的异同

  (1)中间件是ASPNET Core这基础提供的能,而"过滤器(Filter)"是ASPNET Core MVC中提供的功能;ASPNET Core MVC是由MVC中间件提供的架,Filter属于MVC中间件提供能。
  (2)中间件可以处理所有的请求,而Filter只能处理对MVC控制器的请求。
  (3)中间件运行在一个更底层,更抽象的级别,因此在中间件中无法处理MVC中间件特有的概念。
  (4)中间件和Filter可以完成很多相似的功能。“处理异常中间件”和“处理异常Filter”,“请求限流中间件”和“请求限流Filter”等。
  (5)优先选择中间件。但是如果这个组件需要调用MVC相关的类的时候,就用Filter。

4、中间件使用时需要注意的点
(1)HttpContext使用知识
  • 请勿将HttpContext存储在字段中(改为存储IHttpContextAccessor),然后尝试在以后使用它;如下:
public class MyBadType
{
    private readonly HttpContext _context;
    public MyBadType(IHttpContextAccessor accessor)
    {
        _context = accessor.HttpContext;  // 该代码经常在构造函数中捕获 Null 或不正确的 HttpContext。
    }

    public void CheckAdmin()
    {
        if (!_context.User.IsInRole("admin"))
        {
            throw new UnauthorizedAccessException("The current user isn't an admin");
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

  请使用以下的做法

public class MyGoodType
{
    private readonly IHttpContextAccessor _accessor;
    public MyGoodType(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }

    public void CheckAdmin()
    {
        var context = _accessor.HttpContext;
        if (context != null && !context.User.IsInRole("admin"))
        {
            throw new UnauthorizedAccessException("The current user isn't an admin");
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 请勿从多个线程访问 HttpContext(请使用复制的数据 string)。HttpContext 不是线程安全型, 并行从多个线程访问 HttpContext 可能会导致意外的行为,例如挂起、崩溃和数据损坏。
  • 请勿在后台线程中捕获 HttpContext,原因同上。
  • 请勿在后台线程上捕获注入到控制器中的服务。 工作项可能在请求范围之外运行。 ContosoDbContext 的范围限定为请求,从而导致 ObjectDisposedException。可使用以下方式代替:
  • 注入  IServiceScopeFactory 以便在后台工作项中创建范围。 IServiceScopeFactory 是单一实例。
  • 在后台线程中创建新的依赖项注入范围。
  • 不从控制器引用任何内容。
  • 不从传入请求捕获 ContosoDbContext

二、常用中间件

1、OpenAPI规范文档中间件 Swagger

   ASP.NETCore-中间件Middleware(一)_Swagger_Net7

2、请求超时中间件 RequestTimeouts(官方写的)

 

3、缓存中间件组 Caching(内存缓存MemoryCache、分布式缓存Redis、Memcached或SQL Server等、响应缓存ResponseCache)

 

4、输出缓存中间件(版本Net7+;输出缓存与 响应缓存的不同在于 缓存行为可在服务器上配置、缓存存储介质是可扩展的、可限制对访问缓存的访问或仿造缓存)

 

5、响应压缩中间件 ResponseCompression(在无法使用IIS、Apache、Nignx自带的压缩、解压缩技术时使用,如:直接托管在Kestrel、Http.sys服务器上)

 

6、请求解压缩中间件 RequestDecompression(版本Net7+;目的为允许 API 终结点接受包含压缩内容的请求)

 

7、URL重写中间件 Rewrite

  URL 重写是根据一个或多个预定义规则修改请求 URL 的行为。 URL 重写会在资源位置和地址之间创建一个抽象,使位置和地址不紧密相连。应用场景:

  • 暂时或永久移动或替换服务器资源,并维护这些资源的稳定定位符。
  • 拆分在不同应用或同一应用的不同区域中处理的请求。
  • 删除、添加或重新组织传入请求上的 URL 段。
  • 优化搜索引擎优化 (SEO) 的公共 URL。
  • 允许使用友好的公共 URL 来帮助访问者预测请求资源后返回的内容。
  • 将不安全请求重定向到安全终结点。
  • 防止热链接,外部站点会通过热链接将其他站点的资产链接到其自己的内容,从而利用托管在其他站点上的静态资产。
8、速率限制中间件 FixedWindowLimiter(版本Net7+)

 

9、实时通信中间件 SignalR(这里只学Core中的SignalR;内置的技术手段:WebSockets、Server-Sent Events、长轮询;SignalR 自动选择服务器和客户端能力范围内的最佳传输方式)

 

10、Cookie策略中间件组(本地 Cookie、服务器 Session、会话状态 TempData等)
11、身份验证中间件 Authentication(管理用户信息)
(1) 基础使用:管理用户、密码、配置文件数据、角色、声明、令牌、电子邮件确认等;以下为WebAPI的部分使用演示

  ① 使用Claims+ClaimsPrincipal记录用户身份信息:ASP.NET-使用Identity 组件库的Claims记录身份信息

  ②  ClaimsPrincipal序列化记录用户身份信息

  ③ 

(2) 证书验证
(3) 第三方关联登录_ 外部登录登录提供程序(微软官方) Facebook、Twitter、Google和Microsoft等(基于OpenID Connect 和 OAuth 2.0 框架);
(4) 其他第三方登录_ 外部登录登录提供程序 QQ、微信、Gitee、GitHub、GitLab等(基于OpenID Connect 和 OAuth 2.0 框架)。

  OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。

  

ASP.NETCore-中间件Middleware(目录)_文档目录_Net7_中间件

12、授权中间件 Roles(与Cookie策略中间件、身份验证中间件一起使用)

  先认证再授权,UseAuthorization授权UseAuthentication认证后。一般Cookie策略中间件、身份验证中间件、授权中间件一起使用。客户端存储用户信息用户标识,每次请求服务器时将用户信息添加到http请求的header中。浏览器客户端可以使用Cookie或者localstorage存储用户信息,非浏览器端可以使用自定义http通讯使用的变量进行存储。

(1)使用Cookie进行认证与授权

  在浏览器客户端存储用户信息,每次请求服务器时将用户信息添加到http请求的header中,cookie不是很安全。

  ASP.NETCore-中间件Middleware(四)_认证+授权中间件-Cookie

(2)使用Session进行认证与授权

  因为cookie不是很安全,可以选择使用Session把用户信息存储到服务器端,客户端只存储Session ID。每次请求服务器时将用户Session ID标识添加到http请求的header中。

  ASP.NETCore-中间件Middleware(五)_认证+授权中间件-Session

(3)使用JWT进行认证与授权

  与Cookie或Session相比,JWT比较灵活,将用户信息进行JWT加密后,可以存储在客户端(同Cookie),也可以存储在服务器端(同Session ID)。在服务器端存储时可以使用Session,一般直接自定义存储,如:使用Redis、 Memcached、关系型数据库等。

  ASP.NETCore-中间件Middleware(六)_认证+授权中间件-JWT

13、统一授权中间件 IdentityServer(推荐最后学)

 

14、过滤器中间件 Filter 授权过滤器 资源过滤器 操作过滤器 异常过滤器 结果过滤器

  过滤器可以和属性联合使用,属性标识包括: ActionFilterAttribute ExceptionFilterAttribute ResultFilterAttribute FormatFilterAttribute ServiceFilterAttribute TypeFilterAttribute。

  ASP.NETCore-中间件Middleware(二)_全局异常_Net7

15、日志中间件 Logging(需要集成第三方的Nlog、log4等日志框架;集成json格式的日志 AddJsonConsole
(1) ASP.NETCore-Logging(一)_全局异常+Serilog_Net7
(2) ASP.NETCore-Logging(二)_全局异常+Nlog_Net7
16、Http日志中间件 HttpLogging(内置中间件,它记录有关 HTTP 请求和 HTTP 响应的信息(包括标头和整个正文);默认不启用)

 

17、跨域请求(CORS)中间件 Cors

   ASP.NETCore-中间件Middleware(三)_CORS跨域请求_Net7

18、静态文件中间件 UseStaticFiles

 

19、防止跨站脚本 (XSS)中间件Xss(后补)

   https://learn.microsoft.com/zh-cn/aspnet/core/security/cross-site-scripting?view=aspnetcore-6.0

20、高性能 RPC(远程过程调用)框架中间件 gRPC(用在微服务框架的服务间通讯中;写起来麻烦、调起来麻烦,但是传输比http快;推荐版本Net7+)

 

21、消息队列中间件RabbitMQ(或者学Apache Kafka、ActiveMQ;推荐最后学)

 

三、ASP.NET Core 内置中间件列表

中间件

描述

顺序

 身份验证

提供身份验证支持。

在需要 HttpContext.User 之前。 OAuth 回叫的终端。

 授权

提供身份验证支持。

紧接在身份验证中间件之后。

 Cookie 策略

跟踪用户是否同意存储个人信息,并强制实施 cookie 字段(如 secure 和 SameSite)的最低标准。

在发出 cookie 的中间件之前。 示例:身份验证、会话、MVC (TempData)。

 CORS

配置跨域资源共享。

在使用 CORS 的组件之前。 由于 此错误UseCors 当前必须在 UseResponseCaching 之前运行。

 DeveloperExceptionPage

生成一个页面,其中包含的错误信息仅适用于开发环境。

在生成错误的组件之前。 对于开发环境,项目模板会自动将此中间件注册为管道中的第一个中间件。

 诊断

提供新应用的开发人员异常页、异常处理、状态代码页和默认网页的几个单独的中间件。

在生成错误的组件之前。 异常终端或为新应用提供默认网页的终端。

 转接头

将代理标头转发到当前请求。

在使用已更新字段的组件之前。 示例:方案、主机、客户端 IP、方法。

 运行状况检查

检查 ASP.NET Core 应用及其依赖项的运行状况,如检查数据库可用性。

如果请求与运行状况检查终结点匹配,则为终端。

 标头传播

将 HTTP 标头从传入的请求传播到传出的 HTTP 客户端请求中。

 

 HTTP 日志记录

记录 HTTP 请求和响应。

中间件管道的开头。

 HTTP 方法重写

允许传入 POST 请求重写方法。

在使用已更新方法的组件之前。

 HTTPS 重定向

将所有 HTTP 请求重定向到 HTTPS。

在使用 URL 的组件之前。

 HTTP 严格传输安全性 (HSTS)

添加特殊响应标头的安全增强中间件。

在发送响应之前,修改请求的组件之后。 示例:转接头、URL 重写。

 MVC

用 MVC/Razor Pages 处理请求。

如果请求与路由匹配,则为终端。

 OWIN

与基于 OWIN 的应用、服务器和中间件进行互操作。

如果 OWIN 中间件处理完请求,则为终端。

 输出缓存

基于配置提供对缓存响应的支持。

在需要缓存的组件之前。 UseRouting 必须在 UseOutputCaching 之前。 UseCORS 必须在 UseOutputCaching 之前。

 响应缓存

提供对缓存响应的支持。 这需要客户端参与才能正常工作。 使用输出缓存实现完整的服务器控制。

在需要缓存的组件之前。 UseCORS 必须在 UseResponseCaching 之前。 通过对 Razor Pages 等 UI 应用没有好处,因为浏览器通常会设置阻止缓存的请求头。  输出缓存有利于 UI 应用。

 请求解压缩

提供对解压缩请求的支持。

在读取请求正文的组件之前。

 响应压缩

提供对压缩响应的支持。

在需要压缩的组件之前。

 请求本地化

提供本地化支持。

在对本地化敏感的组件之前。 使用  RouteDataRequestCultureProvider 时,必须在路由中间件之后显示。

 终结点路由

定义和约束请求路由。

用于匹配路由的终端。

 SPA

通过返回单页应用程序 (SPA) 的默认页面,在中间件链中处理来自这个点的所有请求

在链中处于靠后位置,因此其他服务于静态文件、MVC 操作等内容的中间件占据优先位置。

 会话

提供对管理用户会话的支持。

在需要会话的组件之前。

 静态文件

为提供静态文件和目录浏览提供支持。

如果请求与文件匹配,则为终端。

 URL 重写

提供对重写 URL 和重定向请求的支持。

在使用 URL 的组件之前。

 W3CLogging

以  W3C 扩展日志文件格式生成服务器访问日志。

中间件管道的开头。

 WebSockets

启用 WebSockets 协议。

在接受 WebSocket 请求所需的组件之前。


作者:꧁执笔小白꧂