一、前言

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# 扩展方法

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/extension-methods

二、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" }
);
});
}

UseDeveloperExceptionPageUseMvc都是接口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.csConfigure方法中注册/引用中间件

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)入门的更多相关文章

  1. ASP.NET Core 基础教程总结 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 基础教程总结 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 基础教程总结 ASP.NET Core 基础教程总算是有了个简单 ...

  2. ASP.NET Core 基础教程-约定 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 基础教程-约定 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 基础教程-约定 因为 ASP.NET Core 是可以跨平台的 ...

  3. 1,[VS入门教程] 使用Visual Studio写c语言 入门与技巧精品文~~~~下载安装篇

    Microsoft Visual Studio是微软(俗称巨硬)公司出品的强大IDE(Integrated Development Environment 集成开发环境),功能强大齐全,界面舒服之类的 ...

  4. Redux 入门教程(二):中间件与异步操作

    上一篇文章,介绍了 Redux 的基本做法:用户发出 Action,Reducer 函数算出新的 State,View 重新渲染. 但是,一个关键问题没有解决:异步操作怎么办?Action 发出以后, ...

  5. ASP.NET Core 入门笔记10,ASP.NET Core 中间件(Middleware)入门

    一.前言 1.本教程主要内容 ASP.NET Core 中间件介绍 通过自定义 ASP.NET Core 中间件实现请求验签 2.本教程环境信息 软件/环境 说明 操作系统 Windows 10 SD ...

  6. 【CC2530入门教程-01】CC2530微控制器开发入门基础

    [引言] 本系列教程就有关CC2530单片机应用入门基础的实训案例进行分析,主要包括以下6部分的内容:[1]CC2530微控制器开发入门基础.[2]通用I/O端口的输入和输出.[3]外部中断初步应用. ...

  7. 吕鑫VC6.0-VS2015 全套C/C++、MFC新手实战入门教程、Linux视频教程 最好的基础入门教程没有之一

    本课程包括:[1]C语言(1个月)[2]C++语法与数据结构(1个月)) [3]MFC项目开发(1个月)[4]Linux项目开发(1个月)往届的授课视频都已经上传到百度网盘,请同学们按照视频教程提前掌 ...

  8. Prometheus 入门教程(一):Prometheus 快速入门

    文章首发于[陈树义]公众号,点击跳转到原文:https://mp.weixin.qq.com/s/ZXlBPHGcWeYh2hjBzacc3A Prometheus 是任何一个高级工程师必须要掌握的技 ...

  9. 2,[VS入门教程] 使用Visual Studio写c语言 入门与技巧精品文~~~~优化篇

    本文导航: 关闭界面特效以提高流畅度 解决调试时出现"无法查找或打开PDB文件"的符号问题 注册微软账号并在vs登录 使用Visual Studio Team Services,同 ...

随机推荐

  1. [Swift]LeetCode879. 盈利计划 | Profitable Schemes

    There are G people in a gang, and a list of various crimes they could commit. The i-th crime generat ...

  2. [Swift]LeetCode909. 蛇梯棋 | Snakes and Ladders

    On an N x N board, the numbers from 1 to N*N are written boustrophedonically starting from the botto ...

  3. 在admui中怎样上传本地文件?

    1.首先需要引入一些插件 css: <link rel="stylesheet" href="/vendor/blueimp-file-upload/jquery. ...

  4. Python档案袋(函数与函数装饰器 )

    特点:代码复用.可扩展.保持一致性 函数简单的实现,返回值的不同: #定义方法 def funx1(): pass def funx2(): return 0 def funx3(): return ...

  5. vue中央事件总线eventBus的简单理解和使用

    公共事件总线eventBus的实质就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件间的通信.它是实现非父子组件通信的一种解决方案. 用法如下: 第一步:项目中创建一个js文件(我通 ...

  6. Linux清空文件内容

    日志文件太多,需要清空: echo "" > mylog.log

  7. 课程五(Sequence Models),第三周(Sequence models & Attention mechanism) —— 2.Programming assignments:Trigger word detection

    Expected OutputTrigger Word Detection Welcome to the final programming assignment of this specializa ...

  8. Netty(三) 什么是 TCP 拆、粘包?如何解决?

    前言 记得前段时间我们生产上的一个网关出现了故障. 这个网关逻辑非常简单,就是接收客户端的请求然后解析报文最后发送短信. 但这个请求并不是常见的 HTTP ,而是利用 Netty 自定义的协议. 有个 ...

  9. TypeError: unorderable types: str() >= int()

    1.问题描述 age=input('please enter your age') if age >=18: print('your age is',age) print('adult') el ...

  10. 【Python3爬虫】12306爬虫

    此次要实现的目标是登录12306网站和查看火车票信息. 具体步骤 一.登录 登录功能是通过使用selenium实现的,用到了超级鹰来识别验证码.没有超级鹰账号的先注册一个账号,充值一点题分,然后把下载 ...