刚开始摸索C# MVC,也只是按图索骥,对C#的特性不是很懂,耐心看完相关文章,对特性的使用有了进一步理解。
1.特性类的命名规范:特性也是一个类,必须继承于System.Attribute类,命名规范为“类名”+Attribute。不管是直接还是间接继承,都会成为一个特性类,特性类的声明定义了一种可以放置在声明之上新的特性。
2.特性的使用:[特性类名(不需要后缀Attribute)(公共属性=值, 公共属性=值...)]放置于类、方法、字段、属性、结构体...前修饰。
如:
//在Person类上标记ClassMsg特性 [ClassMsg(Msg = "这是关于人的姓名信息的类")] class Person { //在_name字段上应用ClassMsg特性 [ClassMsg("这是存储姓名的字段")] string _name; //[ClassMsg("这是读写姓名字段的属性")] public string Name { get { return _name; } set { _name = value; } } }
3.特性类的应用限定修饰:
使用AttributeUsage,来控制如何应用新定义的特性,放置于特性类定义前。
[AttributeUsageAttribute(AttributeTargets.All //可以应用到任何元素 ,AllowMultiple=true, //允许应用多次,我们的定值特性能否被重复放在同一个程序实体前多次。 ,Inherited=false,//不继承到派生 )]
4.特性的应用
(1).net中特性用来处理多种问题,比如序列化、程序的安全特性、防止即时编译器对程序代码进行优化从而代码容易调试等等。
定植特性的本质上是一个类的元素上去添加附加信息,并在运行其通过反射得到该附加信息(在使用数据实体对象时经常用到)
(2)Attribute 作为编译器的指令时的应用
Conditional:起条件编译的作用,只有满足条件,才允许编译器对它的代码进行编译。一般在程序调试的时候使用
DllImport: 用来标记费.net的函数,表明该方法在一个外部的DLL中定义。
Obsolete: 这个属性用来标记当前的方法已经废弃,不再使用
注:Attribute是一个类,因此DllImport也是一个类,Attribute类是在编译的时候实例化,而不是像通常那样在运行时实例化。
CLSCompliant: 保证整个程序集代码遵守CLS,否则编译将报错。
昨天写的《mvc4 利用filters特性来 实现自己的权限验证》 不需要注册全局的Filters来实现,即第2步不需要。全局的Filter所有的请求都会都会触发。
修改为:
mvc4 利用特性类过滤,实现自己的权限验证
1.新建一个特性类AdminAuthorize继承ActionFilterAttribute。重写OnActionExecuting,在执行action前执行,在这里进行权限判断,在switch可定义多种权限。
代码:Filters/AdminAuthorizeAttribute.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Web; 6 using System.Web.Mvc; 7 using System.Web.Profile; 8 using System.Web.Routing; 9 using System.Web.Security; 10 namespace XyguiMvcApp.Filters 11 { 12 //限制Attribute类的使用 13 [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)] 14 public class AdminAuthorizeAttribute : ActionFilterAttribute 15 { 16 /// <summary> 17 /// 角色 18 /// </summary> 19 private string role = ""; 20 /// <summary> 21 /// 摘要:获取或设置用户角色。 22 // 返回结果:用户角色。 23 /// </summary> 24 public string Role 25 { 26 get { return role; } 27 set { role = value; } 28 } 29 30 public override void OnActionExecuting(ActionExecutedContext filterContext) 31 { 32 switch (role) 33 { 34 case "Admin": //Admin角色权限检查。 35 var cookie = System.Web.HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 36 if (cookie != null && FormsAuthentication.Decrypt(cookie.Value).UserData == role) 37 { 38 //验证通过 39 } 40 else 41 { 42 string returnUrl = HttpContext.Current.Request.Url.PathAndQuery; 43 var url = FormsAuthentication.LoginUrl + "?returnUrl=" + HttpUtility.UrlEncode(returnUrl); 44 //HttpContext.Current.Response.Redirect(url, true);//进入action 45 //filterContext.HttpContext.Response.Redirect(url);//进入action 46 /*filterContext.Result = new RedirectToRouteResult( //不进入action 47 new RouteValueDictionary 48 { 49 { "action", "Login" }, 50 { "controller", "Admin" }, 51 {"returnUrl", returnUrl} 52 });*/ 53 filterContext.Result = new RedirectResult(url);//不进入action,转到登录页面。 54 } 55 56 break; 57 case "Anyone": //任何人。 58 59 break; 60 case "Guest": //Guest权限 61 62 break; 63 default: 64 65 break; 66 67 } 68 69 } 70 } 71 }
3.在action前添加特性[AdminAuthorize(Role = "Admin")] ,这里断点发现只有第一次调用action才实例化AdminAuthorizeAttribute类,而OnActionExecuted每次调用action都会触发。
如:
1 [AdminAuthorize(Role = "Anyone")] 2 public ActionResult Index() 3 { 4 return View(); 5 } 6 7 [AdminAuthorize(Role = "Admin")] 8 public ActionResult Main() 9 { 10 11 return View(); 12 }
4.配置web.config
<authentication mode="Forms">
<forms name=".AuthAdmin" loginUrl="~/Admin/Login" timeout="30" protection="All" path="/Admin" defaultUrl="/Admin/Main" />
</authentication>
5.在登录action,Login注册船票ticket
1 FormsAuthenticationTicket MyTicket = new FormsAuthenticationTicket 2 ( 3 1, 4 admin.UserName+"," + admin.NickName, 5 DateTime.Now, 6 DateTime.Now.AddMinutes(300), 7 true, 8 "Admin", 9 FormsAuthentication.FormsCookiePath 10 ); 11 12 //添加 Cookies 13 string myHash = FormsAuthentication.Encrypt(MyTicket); 14 HttpCookie myCookie = new HttpCookie(FormsAuthentication.FormsCookieName, myHash); 15 Response.Cookies.Add(myCookie);