1.介绍
中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:
- 选择是否将请求传递到管道中的下一个组件。
- 可在调用管道中的下一个组件前后执行工作。
2.使用 IApplicationBuilder 创建中间件管道
ASP.NET Core 请求管道包含一系列请求委托,依次调用。每个委托均可在下一个委托前后执行操作,委托还可以决定不将请求传递给下一个委托,这就是对请求管道进行短路。

public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
}
}
警告:在向客户端发送响应后,请勿调用 next.Invoke。
3.中间件顺序(常见应用方案)
- 异常/错误处理
- HTTP 严格传输安全协议
- HTTPS 重定向
- 静态文件服务器
- Cookie 策略实施
- 身份验证
- 会话
- MVC
4.Use、Run 和 Map
Use方法可使管道短路(即不调用next请求委托);Run是一种约定,某些中间件组件公开在管道末尾运行的Run[Middleware]方法;Map扩展用作约定来创建管道分支,Map*基于给定请求路径的匹配项来创建请求管道分支。如果请求路径以给定路径开头,则执行分支;- 使用
Map时,将从HttpRequest.Path中删除匹配的路径段,并针对每个请求将该路径段追加到HttpRequest.PathBase; MapWhen(IApplicationBuilder, Func<HttpContext,Boolean>, Action<IApplicationBuilder>)基于给定谓词的结果创建请求管道分支;Map支持嵌套;Map可同时匹配多个段;
- 使用
5.内置中间件
| 中间件 | 描述 | 顺序 |
|---|---|---|
| 身份验证 | 提供身份验证支持。 | 在需要 HttpContext.User 之前。OAuth 回叫的终端。 |
| Cookie 策略 | 跟踪用户是否同意存储个人信息,并强制实施 cookie 字段(如 secure 和 SameSite)的最低标准。 | 在发出 cookie 的中间件之前。 示例:身份验证、会话、MVC (TempData)。 |
| CORS | 配置跨域资源共享。 | 在使用 CORS 的组件之前。 |
| 诊断 | 配置诊断。 | 在生成错误的组件之前。 |
| 转接头 | 将代理标头转发到当前请求。 | 在使用已更新字段的组件之前。 示例:方案、主机、客户端 IP、方法。 |
| HTTP 方法重写 | 允许传入 POST 请求重写方法。 | 在使用已更新方法的组件之前。 |
| HTTPS 重定向 | 将所有 HTTP 请求重定向到 HTTPS(ASP.NET Core 2.1 或更高版本)。 | 在使用 URL 的组件之前。 |
| HTTP 严格传输安全性 (HSTS) | 添加特殊响应标头的安全增强中间件(ASP.NET Core 2.1 或更高版本)。 | 在发送响应之前,修改请求的组件之后。 示例:转接头、URL 重写。 |
| MVC | 用 MVC/Razor Pages 处理请求(ASP.NET Core 2.0 或更高版本)。 | 如果请求与路由匹配,则为终端。 |
| OWIN | 与基于 OWIN 的应用、服务器和中间件进行互操作。 | 如果 OWIN 中间件处理完请求,则为终端。 |
| 响应缓存 | 提供对缓存响应的支持。 | 在需要缓存的组件之前。 |
| 响应压缩 | 提供对压缩响应的支持。 | 在需要压缩的组件之前。 |
| 请求本地化 | 提供本地化支持。 | 在对本地化敏感的组件之前。 |
| 路由 | 定义和约束请求路由。 | 用于匹配路由的终端。 |
| 会话 | 提供对管理用户会话的支持。 | 在需要会话的组件之前。 |
| 静态文件 | 为提供静态文件和目录浏览提供支持。 | 如果请求与文件匹配,则为终端。 |
| URL 重写 | 提供对重写 URL 和重定向请求的支持。 | 在使用 URL 的组件之前。 |
| WebSockets | 启用 WebSockets 协议。 | 在接受 WebSocket 请求所需的组件之前。 |
6.编写中间件
6.1 内嵌
app.Use((context, next) =>
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
// Call the next delegate/middleware in the pipeline
return next();
});
6.2 类(推荐)
public class RequestCultureMiddleware
{
private readonly RequestDelegate _next;
public RequestCultureMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
// Call the next delegate/middleware in the pipeline
await _next(context);
}
}
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
中间件应通过在其构造函数中公开其依赖项来遵循显式依赖项原则。
7.按请求依赖项
由于中间件是在应用启动时构造的,而不是按请求构造的,故需要注意生命周期。可考虑将依赖服务添加到 Invoke 方法签名。
// IMyScopedService is injected into Invoke
public async Task Invoke(HttpContext httpContext, IMyScopedService svc)
{
svc.MyProperty = 1000;
await _next(httpContext);
}
本文介绍了ASP.NET Core中间件,它是装配到应用管道处理请求和响应的软件。阐述了使用其创建中间件管道的方式,包括请求委托的调用及短路情况。还说明了中间件顺序的常见应用方案,介绍了Use、Run和Map的用法,提及内置中间件,讲解了编写中间件的内嵌和类方式,以及按请求依赖项的注意点。
910

被折叠的 条评论
为什么被折叠?



