29
2018
03

asp.net core 中间件的开发、使用

一、ASP.NET Core 中间件简介

中间件是一种装配到应用程序管道以处理请求和响应的软件。 每个组件可进行以下操作:

选择是否将请求传递到管道中的下一个组件。

可在调用管道中的下一个组件前后执行工作。


中间件在请求过程中执行顺序示意图:


二、ASP.NET Core中间件开发和使用

1、新建项目、项目基础功能配置

1.1 新建asp.net core web 应用程序



1.2 将 Properties/launchSettings.json 文件中两处端口号 都改为5000,一个是vs(iis)运行时的端口号,一个是直接命令行(dotnet run)运行时的端口号


1.3 Huanent.Logging.File包用来记录日志

安装nuget包:Huanent.Logging.File(依赖项:Microsoft.Extensions.Logging.Console) 用来记录文本日志和console日志

(源码在:https://github.com/huanent/Huanent.Logging


在根目录加配置文件:appsettings.json,内容:

{
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "File": {
      "LogLevel": {
        "Default": "Information"
      }
    }
  }
}


修改 Startup.cs,方法Configure 加参数 ILoggerFactory loggerFactory,然后在方法内部加代码:

loggerFactory.AddConsole(minLevel: LogLevel.Information);//启用控制台输出log中间件


修改Program.cs,在 .Build() 前面,加一行代码:

.ConfigureLogging(builder => builder.AddFile())//启用文本日志


2、开发中间件示例

2.1 记录请求者IP中间件开发(带输入参数)


中间件类:RequestIPMiddleware.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
namespace MiddleWareTest
{
    /// <summary>
    /// 模拟记录请求者IP、请求Path中间件
    /// </summary>
    public class RequestIPMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger _logger;
        private readonly RequestIPOptions _option;
        public RequestIPMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IOptions<RequestIPOptions> options)
        {
            _next = next;
            _logger = loggerFactory.CreateLogger<RequestIPMiddleware>();
            if (options != null)
            {
                _option = options.Value;
            }
        }
        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path.HasValue && context.Request.Path.Value != "/favicon.ico")
            {
                var ip = context.Connection.RemoteIpAddress.ToString();
                if (_option == null || _option.LogType == 0 || (ip != "127.0.0.1" && ip != "::1"))
                    _logger.LogInformation("User IP:{0},path:{1}", ip, context.Request.Path);
            }
            await _next.Invoke(context);
        }
    }
    public static class RequestIpExtensions
    {
        public static IApplicationBuilder UseRequestIP(this IApplicationBuilder app)
        {
            if (app == null)
            {
                throw new ArgumentNullException(nameof(app));
            }
            return app.UseMiddleware<RequestIPMiddleware>();
        }
        public static IApplicationBuilder UseRequestIP(this IApplicationBuilder app, RequestIPOptions options)
        {
            if (app == null)
            {
                throw new ArgumentNullException(nameof(app));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            return app.UseMiddleware<RequestIPMiddleware>(Options.Create(options));
        }
    }
}


参数类:RequestIPOptions.cs

using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MiddleWareTest
{
    public class RequestIPOptions : IOptions<RequestIPOptions>
    {
        /// <summary>
        /// 记录类型,0:默认全部,1:非local请求
        /// </summary>
        public int LogType { get; set; }
        RequestIPOptions IOptions<RequestIPOptions>.Value
        {
            get
            {
                return this;
            }
        }
    }
}


2.2 权限验证中间件开发


MyAuthMiddleware.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace MiddleWareTest
{
    /// <summary>
    /// 模拟权限验证中间件
    /// </summary>
    public class MyAuthMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger _logger;

        public MyAuthMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
        {
            _next = next;
            _logger = loggerFactory.CreateLogger<MyAuthMiddleware>();

        }

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path.HasValue)
            {
                if(context.Request.Path.Value == "/favicon.ico")
                {
                    return;
                }
                //这里模拟用户无权限访问
                if (context.Request.Path.Value == "/Forbidden")
                {
                    _logger.LogInformation("禁止访问");
                    context.Response.StatusCode = (int)HttpStatusCode.Forbidden;//可以直接返回状态码
                    //context.Response.Redirect("/403.html");//直接跳转到提示页
                    return;
                }
                //这里模拟用户请求报错
                else if (context.Request.Path.Value == "/InternalServerError")
                {
                    _logger.LogInformation("服务器错误");
                    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;//可以直接返回状态码
                    //context.Response.Redirect("/500.html");//直接跳转到提示页
                    return;
                }
                else
                {
                    _logger.LogInformation("权限正常");
                }
                //验证通过,走正常流程(不阻碍正常流程)
            }

            await _next.Invoke(context);
        }
    }

    public static class MyAuthExtensions
    {
        public static IApplicationBuilder UseMyAuth(this IApplicationBuilder app)
        {
            if (app == null)
            {
                throw new ArgumentNullException(nameof(app));
            }
            return app.UseMiddleware<MyAuthMiddleware>();
        }
    }
}


3、中间件的使用


在 Startup.cs,方法 Configure中,加入调用中间件的方法:

            app.UseRequestIP(new RequestIPOptions()
            {
                LogType = 0
            });//使用自已写的中间件
            
            app.UseMyAuth();

这个顺序,也是请求调用的顺序。


4、查看执行结果

运行项目,浏览器分别以下地址:

http://localhost:5000/


http://localhost:5000/Forbidden


浏览器显示:



日志:bin\Debug\netcoreapp2.0\logs\20180329.txt

-----2018/03/29 15:52:48-----
Information:Microsoft.AspNetCore.Hosting.Internal.WebHost
Request starting HTTP/1.1 GET http://localhost:5000/  
-----End-----
-----2018/03/29 15:52:48-----
Information:MiddleWareTest.RequestIPMiddleware
User IP:::1,path:/
-----End-----
-----2018/03/29 15:52:48-----
Information:MiddleWareTest.MyAuthMiddleware
权限正常
-----End-----
-----2018/03/29 15:52:48-----
Information:Microsoft.AspNetCore.Hosting.Internal.WebHost
Request finished in 34.9226ms 200 
-----End-----

-----2018/03/29 15:53:01-----
Information:Microsoft.AspNetCore.Hosting.Internal.WebHost
Request starting HTTP/1.1 GET http://localhost:5000/Forbidden  
-----End-----
-----2018/03/29 15:53:01-----
Information:MiddleWareTest.RequestIPMiddleware
User IP:::1,path:/Forbidden
-----End-----
-----2018/03/29 15:53:01-----
Information:MiddleWareTest.MyAuthMiddleware
禁止访问
-----End-----
-----2018/03/29 15:53:01-----
Information:Microsoft.AspNetCore.Hosting.Internal.WebHost
Request finished in 2.0393ms 403 
-----End-----



demo下载:http://cdn01.pukuimin.top/zb_users/upload/2018/MiddleWareTest.zip

git地址:https://gitee.com/pukuimin/MiddleWareTest.git



附参考链接:


windows net core sdk下载:

https://www.microsoft.com/net/download/windows


aspnet core log4net 配置:

https://www.cnblogs.com/linezero/p/log4net.html


微软中间件介绍:

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/index?tabs=aspnetcore2x


旧的httpModule、httpHandler与net core中间件之间的迁移(系统由英文翻译,语句不通,可直接看英文)

https://docs.microsoft.com/zh-cn/aspnet/core/migration/http-modules




版权声明:
作者:真爱无限 出处:http://www.pukuimin.top 本文为博主原创文章版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.
« 上一篇下一篇 »

相关文章:

评论列表:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。