一.授权过滤器:AuthorizationFilters
二.动作过滤:ActionFilters
三.响应过滤:ResultFilters
四.异常过滤:ExceptionFilters
========================================================================================================================
一。授权过滤,这里以登陆账号密码,角色id不同进行过滤。
1.添加一个过滤类 , 用于过滤掉和角色id不符合要求的账号。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using Newtonsoft.Json; 2 using Solution.Models; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Web; 7 using System.Web.Mvc; 8 using System.Web.Security; 9 10 namespace Solution.Filter 11 { 12 public class UserAuthorize : AuthorizeAttribute 13 { 14 //允许的角色id集合 15 public string[] x { get; set; } 16 17 /// <summary> 18 /// 请求授权时调用相关的参数 19 /// </summary> 20 /// <param name="filterContext"></param> 21 public override void OnAuthorization(AuthorizationContext filterContext) 22 { 23 string[] str = Roles.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); 24 x = new string[str.Length]; 25 for (int i = 0; i < str.Length; i++) 26 { 27 x[i] = str[i]; 28 } 29 base.OnAuthorization(filterContext); 30 } 31 32 protected override bool AuthorizeCore(HttpContextBase httpContext) 33 { 34 var thisUser = UserHelper.user; 35 bool status = true; 36 //判断是否登陆 37 if (!HttpContext.Current.User.Identity.IsAuthenticated) 38 { 39 return false; 40 } 41 42 //判断角色 43 if (x.Count() > 0 && status==true) 44 { 45 status = x.Contains(thisUser.role); 46 } 47 48 return status; 49 50 } 51 } 52 53 54 55 56 }
2.在Home控制器下添加对应的登陆和退出方法,登陆后跳转的页面。
创建LogDto类,用于封装登陆时需填写的属性
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Solution.Model 8 { 9 public class LogDto 10 { 11 public string Account { get; set; } 12 13 public string PassWord { get; set; } 14 } 15 }
创建UserIdEntity类,用于封装存入cookie的票据信息
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Solution.Models { public class UserIdEntity { public string Account { get; set; } public string PassWord { get; set; } public string role { get; set; } } }
创建ResponseMsg类,用于方法返回的结果信息
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Solution.Common 8 { 9 public class ResponseMsg 10 { 11 /// <summary> 12 /// 默认构造函数 13 /// </summary> 14 public ResponseMsg() 15 { 16 } 17 18 /// <summary> 19 /// 设置初始值 20 /// </summary> 21 /// <param name="_Status"></param> 22 public ResponseMsg(ActonState _Status) 23 { 24 _status = _Status; 25 } 26 27 public ActonState _status; 28 29 public ActonState Status 30 { 31 get { return _status; } 32 set { _status = value; } 33 } 34 35 36 public string Msg { get; set; } 37 38 public string LoadUrl { get; set; } 39 40 public object Data { get; set; } 41 42 } 43 44 public enum ActonState 45 { 46 Default = 0,//默认 47 48 Success = 1, //成功 49 50 Failure = 2,//失败 51 52 ServerError = 3,//服务错误 53 54 Others = 4 //其它 55 } 56 }
在Home控制器下编写登陆方法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
[HttpPost]//只允许post请求 public ActionResult LogOn(LogDto logdto) { string name = logdto.Account; string pwd = logdto.PassWord; ResponseMsg response = new ResponseMsg() { Status = ActonState.Default }; if ("Admin".Equals(name) && "123456".Equals(pwd)) { UserIdEntity identity = new UserIdEntity() { Account = name, PassWord = pwd, role = "1" }; //创建Form票据 FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, name, DateTime.Now, DateTime.Now.AddHours(1), false, JsonConvert.SerializeObject(identity)); //将票证转为字符串(加密) string str = FormsAuthentication.Encrypt(ticket); //将该票证存到cookie中 //FormsAuthentication.SetAuthCookie(str,true); HttpCookie coo = new HttpCookie("DIQx", str); //cookie名称必须与配置中名称相同,否则读取不到userdata Response.Cookies.Add(coo); response.LoadUrl = "/Home/Main"; response.Status = ActonState.Success; } else { response.Status = ActonState.Default; } return Json(response); }
要跳转的页面,这里只允许角色Id为(1,2,3)中的其中的一个进入。且[Roles=""]标记为固定写法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 [UserAuthorize(Roles="1,2,3")] 2 public ActionResult Main() 3 { 4 return View(); 5 }
退出登陆
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
[AllowAnonymous] //允许匿名 public ActionResult OutLogon() { Session.Abandon(); FormsAuthentication.SignOut(); return RedirectToAction("Index","Home"); }
在Web.config文件里 <system.web> 下添加配置如下,
<authentication mode="Forms">
<forms loginUrl="~/Home/Index" name="DIQx" timeout="2880" />
</authentication>
注:name="DIQx" 这个name值和登陆时把票据存入cookie时的cookie名称相同。
测试一下。
①什么也不填,直接地址栏输入要跳转的页面
②账号或密码输入错误的。
③角色id不是(1,2,3)中的一个
以上三种情况都会被阻止,并且跳转至刚才在WebConfig中配置的url地址
满足正确条件,返回Main页面
二。动作过滤 这里编写一个WebApi,对api方法进行加密。
编写过滤类,重写OnActionExecuting方法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 6 7 using System.Net.Http; 8 using Solution.Common; 9 using System.Web.Http.Controllers; 10 using System.Web.Http.Filters; 11 namespace Solution.Filter 12 { 13 public class SecreKeyAttribute : ActionFilterAttribute 14 { 15 16 public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) 17 { 18 19 ResponseMsg response = new ResponseMsg() { Status = ActonState.Default }; 20 21 //var Ticket = actionContext.ActionArguments["Ticket"];//get请求时带的参数 22 23 var Ticket = System.Web.HttpContext.Current.Request["Ticket"]; 24 25 if (Ticket == null) 26 { 27 response.Msg = "请传入密钥!"; 28 actionContext.Response = actionContext.Request.CreateResponse(System.Net.HttpStatusCode.OK, response); 29 } 30 else 31 { 32 string SecrtetKey = Ticket.ToString(); 33 if (!SecrtetKey.Equals("88888888")) 34 { 35 response.Msg = "密钥错误!"; 36 actionContext.Response = actionContext.Request.CreateResponse(System.Net.HttpStatusCode.OK, response); 37 } 38 } 39 base.OnActionExecuting(actionContext); 40 41 } 42 43 44 public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 45 { 46 47 base.OnActionExecuted(actionExecutedContext); 48 } 49 50 } 51 }
编写WebApiConfig配置文件,
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Http; 6 7 namespace Solution.Models 8 { 9 public class WebApiConfig 10 { 11 public static void Register(HttpConfiguration config) 12 { 13 //config.MapHttpAttributeRoutes(); 14 15 config.Routes.MapHttpRoute( 16 name: "DefaultApi",//默认请求api地址 17 routeTemplate: "api/{controller}/{action}/{id}", //例如: 18 http://localhost:41464/api/ScreateKey/GetInfo 19 defaults: new { id = RouteParameter.Optional }); 20 } 21 } 22 }
在Golba.asax中Application_Start()方法下加入刚才的WebApi文件配置
WebApiConfig.Register(GlobalConfiguration.Configuration);
创建对应的api方法,并加入 [SecreKey]标签
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using Solution.Common; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Web; 6 using System.Web.Http; 7 8 using System.Net; 9 using System.Net.Http; 10 using Solution.Filter; 11 12 13 namespace Solution.Controllers 14 { 15 public class ScreateKeyController : ApiController 16 { 17 18 19 // GET: ScreateKey 20 [SecreKey] 21 [HttpPost] 22 public ResponseMsg GetInfo([FromBody]string Ticket) 23 { 24 ResponseMsg response = new ResponseMsg() { Status = ActonState.Default }; 25 response.Msg = "密钥正确时,会返回这个结果"; 26 return response; 27 } 28 } 29 }
注:这里用的是post请求。 参数必须带上这个[FromBody],不然请求不到。而且这个[FromBody]只能用一次,如果有多个参数就只能封装到一个类里面。
测试一下。正确密钥 “8888888”
密钥错误:
密钥正确:
三。结果过滤
添加一个过滤特性类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using Solution.Common; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Web; 6 using System.Web.Mvc; 7 8 namespace Solution.Filter 9 { 10 public class ResultAttribute : ActionFilterAttribute 11 { 12 public override void OnResultExecuting(ResultExecutingContext resultContext) 13 { 14 ResponseMsg response = new ResponseMsg() { Status = ActonState.Default }; 15 resultContext.HttpContext.Response.Write("<br/> 结果返回之前执行"); 16 base.OnResultExecuting(resultContext); 17 } 18 19 public override void OnResultExecuted(ResultExecutedContext resultContext) 20 { 21 ResponseMsg response = new ResponseMsg() { Status = ActonState.Default }; 22 resultContext.HttpContext.Response.Write("<br/> 结果返回之后执行"); 23 base.OnResultExecuted(resultContext); 24 } 25 } 26 }
在Home控制器添加一个视图,并添加[Result]标签
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 [Result] 2 public ActionResult FunResult() 3 { 4 return View(); 5 }
在FunResult.cshtml页面加入如下代码:
@{
Response.Write("<br/> 返回的结果");
}
测试一下,得到结果如下图:
四。异常过滤
创建一个发生错误时跳转的页面
添加一个异常过滤特性类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 6 using System.Web.Mvc; 7 8 namespace Solution.Filter 9 { 10 //异常过滤器 11 public class HandErrorAttribute :HandleErrorAttribute 12 { 13 //程序中任何一个地方发生异常都会处理 14 public override void OnException(ExceptionContext filterContext) 15 { 16 //获取异常对象 17 Exception ex = filterContext.Exception; 18 19 //记录日志 20 21 //发生错误后,跳转的页面 22 filterContext.Result = new RedirectResult("/Home/Error"); 23 24 //告知异常已被处理。如果没有则按照系统正常的异常处理流程走! 25 filterContext.ExceptionHandled = true; 26 27 } 28 } 29 }
在App_Start文件夹下创建FilterConfig文件
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using Solution.Filter; 2 using System.Web; 3 using System.Web.Mvc; 4 5 namespace Solution 6 { 7 public class FilterConfig 8 { 9 public static void RegisterGlobalFilters(GlobalFilterCollection filters) 10 { 11 filters.Add(new HandErrorAttribute()); 12 } 13 } 14 }
在Glabal.asa文件Application_Start()方法下添加刚才的筛选配置
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);