.net5 core webapi进阶之四:自定义中间件的使用

作者:神秘网友 发布时间:2021-02-28 11:50:13

.net5 core webapi进阶之四:自定义中间件的使用

一、什么是中间件先看看微软官方文档对中间件的定义:

官网地址:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/view=aspnetcore-5.0

官网还给出了一张中间件调用的示意图,如下:

简而言之,我们可以把中间件理解成一个功能,它可以对请求进行处理,

并决定是将处理过的请求传递给下一个中间件继续处理还是结束传递,直接发送一个响应给客户端。

二、如果要自定义一个中间件,在请求到达自定义的中间件之前会不会有其他中间件进行处理

如果有,是哪些中间件,其顺序是怎么样的

使用VS2019新建一个WebApi项目后,系统会默认添加一些中间件,比如 app.UseRouting( ); 、

app.UseAuthorization( ); 、app.UseEndpoints( )等(一般是app.UseXxxxx( )这样的形式),

它们位于 Startup.cs 的 Configure(IApplicationBuilder app, IWebHostEnvironment env) 方法中,

其执行顺序即是添加的顺序。对于这些默认的中间件我们暂时不去深究,大概的执行流程

可以参考官方文档中ASP.NET Core MVC 和 Razor Pages 应用的完整请求处理管道示意图,如下:

三、实现一个自定义的中间件。

功能:客户端请求应用程序的一张图片,自定义中间件根据客户端身份信息决定是返回此图片还是返回一张 "没有授权" 的图片。

使用场景:WebApi 给不同的客户端提供服务,不同的客户端有自己的图片文件夹,比如 A公司对应的图片文件夹是 A_Images,

B公司对应的图片文件夹是B_Images,本公司内部管理员对应的图片文件夹是Admin_Images等,

此功能是防止A公司发送的URL错写成B公司的从而造成B公司的图片信息泄露。

扩展:此功能应用到网站中可以稍加修改设计成图片防盗链的功能。

客户端请求的图片如下(lion.jpg):

如果是没授权的客户端,响应如下的一张图片(hellokitty.png):

四、实现步骤。

第1步,预备工作:

新建一个新的 .NET CORE WEBAPI 项目名叫 webapidemo3,

按惯例先删除项目默认生成的 WeatherForecast.cs 和WeatherForecastController.cs,

在Controllers文件夹下新增一个ImagesController的控制器,在此控制器中新增终结点 Demo1( ),代码如下:

namespace webapidemo3
{
    [Route("api/[controller]")]
    [ApiController]
    public class ImagesController : ControllerBase
    {

        [HttpGet]
        [Route("demo1")]
        public IActionResult Demo1()
        {
            return Ok("Test...");
        }

    }
}

第2步,在VS2019解决方案中新建一个 Middlewares 的文件夹,

在里面新增一个名为 ImageRequestMiddleware.cs 的中间件类,如下:

新增 ImageRequestMiddleware.cs 后的默认代码如下:

namespace webapidemo3
{
    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class ImageRequestMiddleware
    {
        private readonly RequestDelegate _next;

        public ImageRequestMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public Task Invoke(HttpContext httpContext)
        {

            return _next(httpContext);
        }
    }

    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class ImageRequestMiddlewareExtensions
    {
        public static IApplicationBuilder UseImageRequestMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddlewareImageRequestMiddleware();
        }
    }
}

要完成的功能需要在 "public Task Invoke(HttpContext httpContext)" 这个函数中进行编码。

类 "public static class ImageRequestMiddlewareExtensions" 的作用是

提供一个扩展方法将这个中间件注册到 HTTP 请求管道中,具体就是在 Startup.cs 的

Configure(IApplicationBuilder app, IWebHostEnvironment env) 方法中加入如下一行代码(见红色部分):

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseImageRequestMiddleware();

            app.UseEndpoints(endpoints =
            {
                endpoints.MapControllers();
            });
        }

注意:中间件的执行是有顺序的,我们自定义的中间件放在客户端经过认证后(app.UseAuthorization( );),

终结点执行前(app.UseEndpoints( )),实际项目中根据需要更改位置。

第3步,编码实现,代码如下。

    public class ImageRequestMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly string _wwwrootPath;
        public ImageRequestMiddleware(RequestDelegate next, IWebHostEnvironment env)
        {
            _next = next;

            //用构造函数注入的方式获取应用程序WebRoot目录的物理地址,即wwwroot文件夹的路径(包含wwwroot)
            _wwwrootPath = env.WebRootPath;
        }

        public Task Invoke(HttpContext httpContext)
        {
            //因为此中间件是在认证中间件之后执行的,
            //所以companyId应该从客户端传递的认证信息中解析出来
            //具体的获取方式和项目的身份认证方式相关,以什么方式写入就以什么方式取出
            //如果是cookie认证,可能的取值方式如下
            //string companyId = httpContext.Request.Cookies["companyId"];

            string companyId = "A1234"; //假设从客户端解析出来的companyId=A1234
            string authorizedImgUrl = "img/" + companyId; //客户端有权限访问的图片路径
              
            string url = httpContext.Request.Path;//客户端访问的网址,

            //只处理图片,如果访问网址不包含图片则直接进入下一个中间件的处理
            //这里根据实际情况可以加入.png/.jpeg/.gif等图片格式的判断
            if (!url.EndsWith(".jpg", true, CultureInfo.CurrentCulture))
            {
                return _next(httpContext);
            }

            string imgPath;
            if (url.IndexOf(authorizedImgUrl)  0) //url中图片路径和授权访问的图片路径一致
            {
                imgPath = url.Substring(url.IndexOf(authorizedImgUrl)); 
            }
            else //url中图片路径和授权访问的图片路径不一致就响应指定的图片
            {
                imgPath = "img/hellokitty.png";
            }

            //输出图片文件
            httpContext.Response.SendFileAsync(Path.Combine(_wwwrootPath, imgPath));

            //中间件短路,不继续执行下一个中间件
            return null; 
        }
    }

注:中间件中如果有Response返回后,不会再向下传递了(即调用 Next( ) 无效了)。

五、测试。

准备工作:

1. 在项目根目录下新增 wwwroot 的文件夹,然后再新增如下的文件夹和文件:

注意:wwwroot这个文件夹名称有特殊的含义,这里通常存放image、js、css等资源,

在网址中访问其中的图片的时候是看不到 wwwroot 这个路径的。

2. 在 Startup.cs 的 Configure( ) 方法中注册自定义的中间件,如下(见红色部分代码),

注意添加的位置,实际项目中如果顺序不恰当可能达不到我们要的效果:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseImageRequestMiddleware();

            app.UseEndpoints(endpoints =
            {
                endpoints.MapControllers();
            });
        }    

3. 打开浏览器,我们先访问终结点 Demo1() 看看会不会错误的把图片显示出来。

是我们期望的结果。

4. 再访问网址: http://localhost:51630/img/A1234/lion.jpg ,结果如下:

有 "img/A1234" 这个路径的权限,可以正常得到图片内容。

5. 最后访问网址: http://localhost:51630/img/B5678/lion.jpg ,结果如下:

没有 "img/B5678" 这个路径的权限,输出指定的图片,达到了期望的结果。

.net5 core webapi进阶之四:自定义中间件的使用 相关文章

  1. .net core 用引用log4net 写入日志

    1. 安装需要应用的程序包 2. 准备配置文件 xml version="1.0" encoding="utf-8"log4net !-- Define some output appenders -- appender name="rollingAppender" type="log4net.Appender.RollingFileAppender" file value="Customlog\log.txt" / !--追加日志

  2. 《Asp.Net Core3 + Vue3入坑教程》 - 配置CORS策略解决跨域问题

    简介 《Asp.Net Core3 + Vue3入坑教程》 此教程适合新手入门或者前后端分离尝试者。可以根据图文一步一步进操作编码也可以选择直接查看源码。每一篇文章都有对应的源码 教程后期会将 .Net Core 3升级成 .Net Core 5 目录 《Asp.Net Core3 + Vue3入坑教程》系

  3. .net5 core webapi进阶之四:异步编程(下篇)BeginInvoke( )/EndInvoke( )的使用

    实现异步操作,除了用 async 和 await 这对组合之外,还可以通过委托对象的 BeginInvoke( ) 和 EndInvoke( ) 来完成 , 为了简化代码,我们直接使用系统为我们提供的内置委托 FuncT1,T2,...TResult 来Demo,代码如下: (注:目前.net5 core 还不支持 BeginI

  4. NetCore-Serilog 按模块区分日志目录

    前段时间,项目有需求,需要将某些模块的日志单独记录文件夹,于是找了一下Serilog的目录配置。 如果是按照appsetting来配置,节点内容大概如下: { "Name": "RollingFile", "Args": { "pathFormat": "Logs/Warning/{Date}.txt", "RestrictedToMinimumLevel"

  5. ModuleNotFoundError: No module named django.core.urlresolvers错误

    继续学习python的脚步。在《Python编程:从入门到实践》中,在引用函数 reverse()时,报 ModuleNotFoundError: No module named 'django.core.urlresolvers'错误 ,查询后发现在Django2.0后,更换了包,原来的 django.core.urlresolvers 包更改为django.urls

  6. Intern Day7 - 近期学习关于ASP.NET Core常见名词总结

    ORM框架:对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。作用:用于实现面向对象编程语言里不同类型系统的数据之间的转换。基本的

  7. .NetCore3.1使用Swagger

    场景,准备使用Core3.1制作SwaggerApi接口 1.项目结构: 2.创建好空项目后,NuGet程序集安装Swashbuckle.AspNetCore 3.StartUp.cs代码(红色部分为配置SwaggerApi的配置代码) public class Startup { public IFreeSql FreeSql { get; private set; } public

  8. netCore 3.1 使用jwt完成登录验证

    nuget安装 Microsoft.AspNetCore.Authentication.JwtBearer 3.1.0 版本 配置appsettings.json "Authentication": { //jwt "JwtBearer": { "IsEnabled": "true", "SecurityKey": "Demo_C421AAEE0D114E9C1", "Issuer": "Demo", "Audience": "Demo", "Expiratio

  9. Intern Day7 - ASP.NET Core路由

    路由介绍 路由是用来把请求映射到路由处理程序。应用程序一启动就配置了路由,并且可以从URL中提取值用于处理请求。它还负责使用 ASP.NET 应用程序中定义的路由来生成链接。 路由的作用:定义用户请求与控制器方法之间的映射关系。 ASP.NET Core中包含两种形

  10. Kubernetes中分布式存储Rook-Ceph的使用:一个ASP.NET Core MVC的案例

    在《Kubernetes中分布式存储Rook-Ceph部署快速演练》文章中,我快速介绍了Kubernetes中分布式存储Rook-Ceph的部署过程,这里介绍如何在部署于Kubernetes的ASP.NET Core MVC的应用程序中使用Rook-Ceph所创建的存储对象。 构建ASP.NET Core MVC (.NET 5)应用程

每天更新java,php,javaScript,go,python,nodejs,vue,android,mysql等相关技术教程,教程由网友分享而来,欢迎大家分享IT技术教程到本站,帮助自己同时也帮助他人!

Copyright 2020, All Rights Reserved. Powered by 跳墙网(www.tqwba.com)|网站地图|关键词