博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.Net Filter原理(使用特性 Attribute)这是一个AOP编程
阅读量:4310 次
发布时间:2019-06-06

本文共 8771 字,大约阅读时间需要 29 分钟。

一、自定义权限认证特性 CheckLoginAttribute

  基于.net core mvc的验证Session登陆状态

1.新建一个.net core mvc项目

2.在Models文件夹下面添加一个类MyAttribute,专门用来保存我们定义的特性

  在这里我只写了CheckLoginAttribute用来验证登陆情况

using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Filters;using System;namespace AttributeStudy.Models{    public class MyAttribute    {    }    public class CheckLoginAttribute : Attribute,IActionFilter    {        public void OnActionExecuted(ActionExecutedContext context)//方法执行后执行        {        }        public void OnActionExecuting(ActionExecutingContext context)//方法执行前执行        {            if(context.HttpContext.Session.GetString("LoginName")==null)            {                context.Result = new RedirectResult("Contact");//如果不存在这个Session则表示登陆不成功,跳到Contact页面            }            else            {          //否则,不做操作。            }        }    }}

  因为这里不是controller,所以,我们要得使用session得用注入的context来调用

  而且,在.Net core使用Sesion还得在Startup添加配置

ConfigureServices下面添加          services.AddSession();Configure下面添加                  app.UseSession();

   HomeController如下:

using AttributeStudy.Models;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;using System.Diagnostics;namespace AttributeStudy.Controllers{    public class HomeController : Controller    {        public IActionResult Index()        {            return View();        }        public void SetSession(int i)//做测试用,添加LogonName这个Session        {            HttpContext.Session.SetString("LoginName", "123456");        }        public void RemoveSession(int i,int j)//做测试用,删除LogonName这个Session        {            HttpContext.Session.Remove("LoginName");        }        [CheckLogin]        public IActionResult About()        {            ViewData["Message"] = "Your application description page.";            return View();        }        public IActionResult Contact()        {            ViewData["Message"] = "Your contact page.";            return View();        }        public IActionResult Error()        {            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });        }    }}

  这样我们检测登陆特性已经可以演示了,启动后,在网页点击About,会先检执行CheckLoginAttribute的OnActionExecuting做登陆验证。

 

 

 

 

 

二、自定义权限认证特性 CustomAuthorizeAttribute

  基于.net mvc 的验证Session登陆状态

1.新建一个.net mvc项目

  添加控制器Login、并在控制器index右键添加index视图

public class LoginController : Controller    {        // GET: Login        public ActionResult Index()        {            return View();        }        public string Login()        {            HttpContext.Session["StudyAOPSession"] = "kxy&123";            return "登录成功";        }        public string Out()        {            HttpContext.Session["StudyAOPSession"] = null;            return "已退出";        }    }

  index视图

@{    ViewBag.Title = "Index";}

请登录!

@Html.ActionLink("登录", "Login", "Login")@Html.ActionLink("退出", "Out", "Login")

2.新建文件夹CustomAttribute,并添加类 CustomAuthorizeAttribute

public class CustomAuthorizeAttribute: AuthorizeAttribute    {
     // 加上这个特性 会先执行这个函数 public override void OnAuthorization(AuthorizationContext filterContext) { var StudyAOPSession = filterContext.HttpContext.Session["StudyAOPSession"]; // 判断登录Session是否存在、账号密码是否正确(这里只是模拟一下) if (StudyAOPSession == null || !StudyAOPSession.ToString().Equals("kxy&123")) { filterContext.Result = new ViewResult() { ViewName = "~/Views/Login/index.cshtml" }; } } }

  这样我们就新建好了一个用来验证登陆的特性

  加特性的三个地方

  1、Action:方法注册、指定某个方法

  2、Controller:控制器注册、指定控制器下面的所有方法

  3、FilterConfig:全局注册,在App_Start 里面的 FilterConfig

public class FilterConfig    {        public static void RegisterGlobalFilters(GlobalFilterCollection filters)        {            filters.Add(new HandleErrorAttribute());            filters.Add(new CustomAuthorizeAttribute());// 我们加的特性        }    }

 3.允许匿名访问  AllowAnonymous

  AllowAnonymous不是添加了就有效,需要在自定义特性判断是否有添加AllowAnonymous,已经添加了就是允许匿名,直接return,不做筛选操作

  修改类:CustomAuthorizeAttribute

public class CustomAuthorizeAttribute : AuthorizeAttribute    {        public override void OnAuthorization(AuthorizationContext filterContext)        {            if (filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))                return;//判断控制器是否允许匿名            if (filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))                return;//判断Action是否允许匿名            var StudyAOPSession = filterContext.HttpContext.Session["StudyAOPSession"];            // 判断登录Session是否存在、账号密码是否正确(这里只是模拟一下)            if (StudyAOPSession == null || !StudyAOPSession.ToString().Equals("kxy&123"))            {                filterContext.Result = new ViewResult()                {                    ViewName = "~/Views/Login/index.cshtml"                };            }        }    }

  AllowAnonymous特性可以注册在Controller或者Action上面

 

 

 

三、自定义捕捉异常特性 CustomHandleErrorAttribute

public class CustomHandleErrorAttribute : HandleErrorAttribute    {        public override void OnException(ExceptionContext filterContext)        {            if (filterContext.ExceptionHandled)                return;//异常已被处理,这里不再处理            filterContext.Result = new ViewResult()            {                //捕捉到未被处理的异常(也就是没有catch掉的异常),转到错误页,显示错误信息                ViewName = "~/Views/Shared/Error.cshtml",                ViewData = new ViewDataDictionary
(filterContext.Exception.Message) }; filterContext.ExceptionHandled = true;//标记已处理 } }

  Error页如下

错误

错误。

处理你的请求时出错。

@Model

  CustomHandleErrorAttribute 可以进行方法、控制器、全局注册

  一般而言,捕捉异常会用全局注册

public class FilterConfig    {        public static void RegisterGlobalFilters(GlobalFilterCollection filters)        {            //filters.Add(new HandleErrorAttribute());//这是自带的异常捕捉特性,现在换成我们自己的            filters.Add(new CustomHandleErrorAttribute());        }    }

  软谋教育举例的七大异常:

    

  可以看出5、6、7 这三个场景并不能被捕捉到,还是会出现异常黄页

  可以通过在Global.asax.cs 添加如下函数进行异常捕捉

///         /// 保底全局异常处理,任何最终没有被处理的异常都会来这里        /// 但是获取的信息比较粗略,所以是作为补充        ///         ///         ///         protected void Application_Error(object sender,EventArgs e)        {            var error = Server.GetLastError();            Server.ClearError();// 将错误清除掉            Response.Write(error.Message);        }

  注意,函数名和参数必须是这样  不能改

  PS:异常捕捉特性可以捕捉  权限认证特性和方法过滤特性里面发送的异常

 

 

 

 

四、自定义方法过滤特性 CustomActionFilterAttribute

  可用于页面压缩

 1.特性代码演示

///     /// 自定义Action过滤特性    ///     public class CustomActionFilterAttribute : ActionFilterAttribute    {        ///         /// 动作执行前        ///         ///         public override void OnActionExecuting(ActionExecutingContext filterContext)        {            filterContext.HttpContext.Response.Write("动作执行前
"); } /// /// 动作执行后 /// /// public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("动作执行后
"); } /// /// 视图加载前 /// /// public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write("视图加载前
"); } /// /// 视图加载后 /// /// public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write("视图加载后
"); } }

  这个特性分别是网页面添加一句话,在Home的About方法注册一下这个特性

[CustomActionFilter]        public ActionResult About()        {            ViewBag.Message = "Your application description page.";            return View();        }

  页面如下:

  从这里我们可以看出,在Action执行前后四个特性函数的执行顺序

2.使用函数 OnActionExecuting 进行页面压缩

  我们先看一下没有压缩的About网页的 请求头 和 响应头

    

  请求头中,页面支持的压缩类型有 gzip,所以,我们可以对这个页面进行 gzip压缩

  响应头中,页面传输数据长度为1830

  接下来看一下特性代码中 OnActionExecuting 函数

public override void OnActionExecuting(ActionExecutingContext filterContext)        {            string acceptEncoding = filterContext.HttpContext.Request.Headers["accept-encoding"];            if (string.IsNullOrEmpty(acceptEncoding))                return;            else            {                if (acceptEncoding.ToLower().Contains("gzip"))                {                    // 页面支持 gzip压缩                    var response = filterContext.HttpContext.Response;                    response.Filter = new GZipStream(response.Filter,CompressionMode.Compress);//对响应流进行gzip压缩                    response.AddHeader("content-encoding", "gzip");//告诉浏览器要解压                }            }        }

  给About添加特性后

    

   回复的页面传输数据长度为 716 ,比之前少了很多,内容编码为gzip,浏览器会自动对页面进行解压

转载于:https://www.cnblogs.com/wskxy/p/9441887.html

你可能感兴趣的文章
第二次冲刺计划周第四天
查看>>
leetcode 120. Triangle
查看>>
边缘网关协议(BGP)
查看>>
github和gitlab并存
查看>>
表单日期点击输入时显示日历表
查看>>
Css中position、float和clear整理
查看>>
JavaScript表单验证
查看>>
Vijos p1123 均分纸牌
查看>>
关于NSDateFormatter的格式-dd是月天,DD是年天
查看>>
各路传奇排序
查看>>
像心跳的方向走
查看>>
收集JavaScript中常用的方法函数
查看>>
2. cgi 结构目录
查看>>
Abp框架下 Area中新建Layout报错的问题
查看>>
linux下修改hosts文件
查看>>
Restful API 设计参考原则
查看>>
两个实用的Python的装饰器
查看>>
将前端所要传的参数设置在一个对象中,将对象转换成字符串往后台传
查看>>
BOM
查看>>
9、连接查询A
查看>>