ASP.NET Core 入门教程 9、ASP.NET Core 中间件(Middleware)入门
一、前言
1、本教程主要内容
- ASP.NET Core 中间件介绍
- 通过自定义 ASP.NET Core 中间件实现请求验签
2、本教程环境信息
| 软件/环境 | 说明 |
|---|---|
| 操作系统 | Windows 10 |
| SDK | 2.1.401 |
| ASP.NET Core | 2.1.3 |
| MySQL | 8.0.x |
| IDE | Visual Studio Code 1.32.3 |
| 浏览器 | Chrome 70 |
| VS Code插件 | 版本 | 说明 |
|---|---|---|
| C# | 1.17.1 | 提供C#智能感知, .NET Core 调试、编译等 |
| vscdoe-solution-explorer | 0.3.1 | 提供解决方案视图 |
本篇代码以下代码进行调整:https://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-02
3、前置知识
可能需要的前置知识
- C# 委托(Delegate)
http://www.runoob.com/csharp/csharp-delegate.html
- C# 扩展方法
二、ASP.NET Core 中间件介绍
1、ASP.NET Core 中间件基本说明
当 ASP.NET Core MVC应用从Kestrel接收到请求,会建立HttpContext并交由Application来处理请求。在Application中会有一个处理该请求的通道,这就是ASP.NET Core 管道,通常称之为:请求处理管道
在这个管道中,有一系列有序处理请求的组件,就是中间件(Middleware)。

图中蓝色的部分可以认为是系统内置比较靠前的中间件或者我们自定义的中间件,MVC是一个特殊的中间件且通常放在最后,所以这里单独画出来
对于MVC中间件,如果请求的URL与路由匹配,那么后面的中间件均不会生效。所以MVC通常放在最后。
ASP.NET Core中会内置一些中间件,例如:身份验证、静态文件处理、MVC等。每个中间件在接受到请求后都可以选择是交由下一个中间件处理还是直接返回结果。例如:
- 身份验证中间件验证未通过会直接引导到登陆页
- 静态文件中间件判断为静态文件就会直接返回静态文件内容
所以,中间件可以理解为请求处理管道中的请求处理器。我们也可以通过自定义中间件注册到管道中来干预请求。
2、ASP.NET Core 中间件基础使用
在程序中,中间件是基于委托来构建的。在应用启动时通过IApplicationBuilder注册到通道中。
具体见启动类Startup.cs:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc(routes =>
{
//配置默认路由
routes.MapRoute(
name: "Default",
template: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
});
}
UseDeveloperExceptionPage、UseMvc都是接口IApplicationBuilder的扩展方法。
三、使用 ASP.NET Core 中间件实现请求验签
如果你开发的API是为手机App服务的,那么你的API是一定要暴露给公网的,如果有人拿到API地址进行非法请求,获取用户信息或者是篡改数据,用户隐私、数据就会受到损害。这是很不安全的,我们可以让客户端请求的时候必须携带签名,在服务器端鉴权(验证签名)通过了再放行,这样就安全很多了。
1、创建验签中间件
在项目Ken.Tutorial.Web创建目录Middlewares,然后创建类:TokenCheckMiddleware.cs
using System;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Ken.Tutorial.Web.Middlewares
{
public class TokenCheckMiddleware
{
private readonly RequestDelegate _next;
public TokenCheckMiddleware(RequestDelegate requestDelegate)
{
this._next = requestDelegate;
}
public Task Invoke(HttpContext context)
{
//先从Url取token,如果取不到就从Form表单中取token
var token = context.Request.Query["token"].ToString() ?? context.Request.Form["token"].ToString();
if (string.IsNullOrWhiteSpace(token))
{
//如果没有获取到token信息,那么久返回token missing
return context.Response.WriteAsync("token missing");
}
//获取前1分钟和当前的分钟
var minute0 = DateTime.Now.AddMinutes(-1).ToString("yyyy-MM-dd HH:mm");
var minute = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
//当token和前一分钟或当前分钟任一时间字符串的MD5哈希一致,就认为是合法请求
if (token == MD5Hash(minute) || token == MD5Hash(minute0))
{
return _next.Invoke(context);
}
//如果token未验证通过返回token error
return context.Response.WriteAsync("token error");
}
public string MD5Hash(string value)
{
using (var md5 = MD5.Create())
{
var result = md5.ComputeHash(Encoding.ASCII.GetBytes(value));
var strResult = BitConverter.ToString(result);
return strResult.Replace("-", "");
}
}
}
}
由于是侧重自定义中间件,所有验签的逻辑就写的非常简单,如果实际项目使用,可以按照自己需求调整
2、创建扩展方法
在Middlewares目录下新建类:MiddlewareExtension.cs
using Microsoft.AspNetCore.Builder;
namespace Ken.Tutorial.Web.Middlewares
{
public static class MiddlewareExtension
{
public static IApplicationBuilder UseTokenCheck(this IApplicationBuilder builder)
{
return builder.UseMiddleware<TokenCheckMiddleware>();
}
}
}
这里我们通过扩展方法,将TokenCheckMiddleware挂在接口IApplicationBuilder上
3、中间件注册/引用
在启动类Startup.cs的Configure方法中注册/引用中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//省略部分代码
app.UseTokenCheck();
app.UseMvc(routes =>
{
//省略路由配置代码
});
}
如果你觉得扩展方法有点多余,也可以直接使用UseMiddleware方法注册
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//省略部分代码
app.UseMiddleware<TokenCheckMiddleware>();
app.UseMvc(routes =>
{
//省略路由配置代码
});
}
这里要注意的是,如果你是一个MVC应用,请一定要把MVC这个中间件作为最后一个注册。因为中间件是按照注册顺序被调用的。如果放在MVC之后,请求的URL也有对应路由适配,那么整个请求已经被MVC接管。后面的中间件就不会被调用了。
4、验签中间件测试
启动应用,然后验证不同情况下的访问结果
| URL | Response |
|---|---|
| localhost:5001 | token missing |
| localhost:5001?token=test | token error |
| localhost:5001?token=3D76FEA1D0ADD0C7639B73023436C6EA | Hello World ! -ken.io |
为了方便测试,MD5哈希的值我们可以在线生成:ttp://tool.chinaz.com/tools/md5.aspx
把当前分钟,例如:2019-03-27 23:23 通过MD5在线生成那就是3D76FEA1D0ADD0C7639B73023436C6EA
四、备注
- 本文代码示例
https://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-09
- 本文参考
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-2.1
- 延伸阅读
https://www.cnblogs.com/artech/p/inside-asp-net-core-pipeline.html
本文首发于我的独立博客:https://ken.io/note/asp.net-core-tutorial-middleware
ASP.NET Core 入门教程 9、ASP.NET Core 中间件(Middleware)入门的更多相关文章
- ASP.NET Core 基础教程总结 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 基础教程总结 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 基础教程总结 ASP.NET Core 基础教程总算是有了个简单 ...
- ASP.NET Core 基础教程-约定 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 基础教程-约定 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 基础教程-约定 因为 ASP.NET Core 是可以跨平台的 ...
- 1,[VS入门教程] 使用Visual Studio写c语言 入门与技巧精品文~~~~下载安装篇
Microsoft Visual Studio是微软(俗称巨硬)公司出品的强大IDE(Integrated Development Environment 集成开发环境),功能强大齐全,界面舒服之类的 ...
- Redux 入门教程(二):中间件与异步操作
上一篇文章,介绍了 Redux 的基本做法:用户发出 Action,Reducer 函数算出新的 State,View 重新渲染. 但是,一个关键问题没有解决:异步操作怎么办?Action 发出以后, ...
- ASP.NET Core 入门笔记10,ASP.NET Core 中间件(Middleware)入门
一.前言 1.本教程主要内容 ASP.NET Core 中间件介绍 通过自定义 ASP.NET Core 中间件实现请求验签 2.本教程环境信息 软件/环境 说明 操作系统 Windows 10 SD ...
- 【CC2530入门教程-01】CC2530微控制器开发入门基础
[引言] 本系列教程就有关CC2530单片机应用入门基础的实训案例进行分析,主要包括以下6部分的内容:[1]CC2530微控制器开发入门基础.[2]通用I/O端口的输入和输出.[3]外部中断初步应用. ...
- 吕鑫VC6.0-VS2015 全套C/C++、MFC新手实战入门教程、Linux视频教程 最好的基础入门教程没有之一
本课程包括:[1]C语言(1个月)[2]C++语法与数据结构(1个月)) [3]MFC项目开发(1个月)[4]Linux项目开发(1个月)往届的授课视频都已经上传到百度网盘,请同学们按照视频教程提前掌 ...
- Prometheus 入门教程(一):Prometheus 快速入门
文章首发于[陈树义]公众号,点击跳转到原文:https://mp.weixin.qq.com/s/ZXlBPHGcWeYh2hjBzacc3A Prometheus 是任何一个高级工程师必须要掌握的技 ...
- 2,[VS入门教程] 使用Visual Studio写c语言 入门与技巧精品文~~~~优化篇
本文导航: 关闭界面特效以提高流畅度 解决调试时出现"无法查找或打开PDB文件"的符号问题 注册微软账号并在vs登录 使用Visual Studio Team Services,同 ...
随机推荐
- [Swift]LeetCode386. 字典序排数 | Lexicographical Numbers
Given an integer n, return 1 - n in lexicographical order. For example, given 13, return: [1,10,11,1 ...
- oracle 合并多个sys_refcursor
一.背景 在数据开发中,有时你需要合并两个动态游标sys_refcursor. 开发一个存储过程PROC_A,这个过程业务逻辑相当复杂,代码篇幅较长.一段时间后要开发一个PROC_B,要用PROC_A ...
- Jmeter-阶梯场景设置
接上一篇[Jmeter-常用线程组设置及场景运行时间计算] Jmeter复杂场景设计,依赖插件jp@gc - Stepping Thread Group (deprecated)和jp@gc - Ul ...
- [Reversing.kr] Easy_KeygenMe Writeup
IDA打开.Main()函数就是关键算法 v6,v7,v8 是连续的 .可看成 L=[16,32,48].输入的name每位分别于L[]异或 得到的值存在v13.然后清空v9的值 ,输入Serial储 ...
- flink metric库的使用和自定义metric-reporter
简单介绍 flink内部实现了一套metric数据收集库. 同时flink自身系统有一些固定的metric数据, 包括系统的一些指标,CPU,内存, IO 或者各个task运行的一些指标.具体包含那些 ...
- IntelliJ IDEA下SVN的配置及使用说明
1 下载及安装SVN客户端. 到官网下载小乌龟SVN客户端,官网地址:https://tortoisesvn.net/downloads.html,根据操作系统情况选择适合版本.比如64为操作系统,如 ...
- 【Storm篇】--Storm从初始到分布式搭建
一.前述 Storm是一个流式处理框架,相比较于SparkStreaming是一个微批处理框架,hadoop是一个批处理框架. 二 .搭建流程 1.集群规划 Nimbus Supervisor ...
- 【干货】.NET WebApi HttpMessageHandler管道
消息拦截器是一个类,接收 HTTP request并返回 HTTP response,Message handler 继承自抽象类 HttpMessageHandler,那么学习消息过滤器之前你应该了 ...
- .NET Core中的路由约束
背景介绍 上周给大家分享了Nancy in .NET Core学习笔记 - 路由之后, 就一直在考虑.NET Core能否实现和Nancy中一样的路由约束, 最近查阅了一下MSDN及一些国外博客, 发 ...
- C#版 - Leetcode 65. 有效数字 - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...