设为首页 加入收藏

TOP

asp.net core 之中间件(一)
2019-09-17 15:14:58 】 浏览:65
Tags:asp.net core 中间件

Http请求资源的过程可以看成一个管道:“Pipe”,并不是所有的请求都是合法的、安全的,其于功能、性能或安全方面的考虑,通常需要在这管道中装配一些处理程序来筛选和加工这些请求。这些处理程序就是中间件。

 

 

 中间件之间的调用顺序就是添加中间件组件的顺序,调用顺序以于应用程序的安全性、性能、和功能至关重要。

如UserDeveloperExceptionPage中间件需要放在第一个被调用位置,因为回应的最后一步需要它来处理异常,如跳转到异常页面这样的操作。UseStaticFiles需要放在UseMvc前,因为Mvc中间件做了路由处理,(wwwroot)文件夹里的图片,js,html等静态资源路径没有经过路由处理,mvc中间件会直接返回404。

可以使用IApplicationBuilder创建中间件,IApplicationBuilder有依赖在StartUp.Configure方法参数中,可以直接使用。一般有三种方法使用中间件:use,run,map。其中如果用run创建中间件的话,第一个run就会中止表示往下传递,后边的use,run,map都不会起到任何作用。

Run:终端中间件,会使管道短路。

           app.Run(async context =>
            {
                await context.Response.WriteAsync("first run");
            });
            app.Run(async context =>
            {
                await context.Response.WriteAsync("second run");
            });        

 只会输出"first run"。 

Map:约束终端中间件,匹配短路管道.匹配条件是HttpContext.Request.Path和预设值

           app.Map("/map1", r =>
            {
                r.Run(async d =>
                {
                    await d.Response.WriteAsync("map1");
                });
            });

            app.Map("/map2", r =>
            {
                r.Run(async d =>
                {
                    await d.Response.WriteAsync("map2");
                });
            });

 访问 https://localhost:5002/map1 返回"map1",访问https://localhost:5002/map2时访问"map2"。都不符合时继续往下走。

Map有个扩展方法MapWhen,可以自定义匹配条件:

  app.MapWhen(context => context.Request.QueryString.ToString().ToLower().Contains("sid"), r =>
            {
                r.Run(async d =>
                {
                    await d.Response.WriteAsync("map:"+d.Request.QueryString);
                });
            });

 Map和Run方法创建的都是终端中间件,无法决定是否继续往下传递,只能中断。

 使用中间件保护图片资源

 为防止网站上的图片资源被其它网页盗用,使用中间件过滤请求,非本网站的图片请求直接返回一张通用图片,本站请求则往下传递,所以run和map方法不适用,只能用use,use方法可以用委托决定是否继续往下传递。

实现原理:模式浏览器请求时,一般会传递一个名称为Referer的Header,html标签<img>等是模拟浏览器请求,所以会带有Referer头,标识了请求源地址。可以利用这个数据与Request上下文的Host比较判断是不是本站请求。有以下几点需要注意:https访问http时有可能不会带着Referer头,但http访问https,https访问http时都会带,所以如果网站启用了https就能一定取到这个Header值。还有一点Referer这个单词是拼错了的,正确的拼法是Refferer,就是早期由于http标准不完善,有写Refferer的,有写Referer的。还有就是浏览器直接请求时是不带这个Header的。这个中间件必需在app.UseStaticFiles()之前,因为UseStaticFiles是一个终端中间件,会直接返回静态资源,不会再往下传递请求,而图片是属于静态资源。

  app.Use(async (context,next) => {
                //是否允许空Referer头访问
                bool allowEmptyReffer=true;
                //过滤图片类型
                string[] imgTypes = new string[] { "jpg", "ico", "png" };
                //本站主机地址
                string oriUrl = $"{context.Request.Scheme}://{context.Request.Host.Value}".ToLower();
                //请求站地址标识
                var reffer = context.Request.Headers[HeaderNames.Referer].ToString().ToLower();
                reffer = string.IsNullOrEmpty(reffer) ? context.Request.Headers["Refferer"].ToString().ToLower():reffer;
                //请求资源后缀
                string pix = context.Request.Path.Value.Split(".").Last();
                if (imgTypes.Contains(pix) && !reffer.StartsWith(oriUrl)&&(string.IsNullOrEmpty(reffer)&&!allowEmptyReffer))
                {
                    //不是本站请求返回特定图片
                    await context.Response.SendFileAsync(Path.Combine(env.WebRootPath, "project.jpg"));
                }
                //本站请求继续往下传递
                await next();
            });

 这样配置虽然可以工作的,但也是有问题的,因为直接发送文件,没有顾得上HTTP的请求状态设置,SendFile后就没管了,当然,本站请求直接next的请求没有问题,因为有下一层的中间件去处理状态码。下面是打印出的异常

fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HLPLOP3KV1UI", Request id &q
首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇.net实现一个简单的通用查询数据.. 下一篇c# Equal函数 and 运算符'==&..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目