在ASP.NET MVC2中使用自定义的AuthorizeAttribute绕过内置的Membership/Role机制

感谢 DSO at http://stackoverflow.com/users/38087/DSO

 

在ASP.NET MVC2中,我们可以使用Authorize Filter限制用户对内容的访问,如

[c-sharp]  view plain copy print ?
  1. [Authorize]  
  2. public class MyController : Controller  
  3. {   
  4.    // ...   
  5. }  
  6. // 或者  
  7. [Authorize(Roles="Admin")]  
  8. public class MyController : Controller  
  9. {   
  10.    // ...   
  11. }  

但前提是要用到Membership / Role机制。 我们要不就使用内置的机制,要不就派生出自己的。

不管怎样,都比较麻烦,其实我们可以绕过这套机制,而且还能使用AuthorizeAttribute。

 

以下是DSO的看法:

 

 

With MVC it is simple to bypass the Membership and Role provider framework altogether. Sometimes it is easier to do this than to implement custom Membership/Role providers, in particular if your authn/authz model doesn't quite fit the mold of those providers.

First, you should realize that you don't need to write everything from scratch, you can use the core Forms authentication API, which can be used independently of the Membership/Role provider framework:

  • FormsAuthentication.SetAuthCookie - Call this after user has been authenticated, specify the user name
  • Request.IsAuthenticated - Returns true if SetAuthCookie was called
  • HttpContext.Current.User.Identity.Name - Returns the user name specified in the call to SetAuthCookie

So here is what you do in MVC to bypass the Membership/Role provider:

  1. Authentication : In your controller, authenticate the user using your custom logic.If successful, callFormsAuthentication.SetAuthCookie with the user name.

  2. Authorization : Create a custom authorize attribute (deriving from AuthorizeAttribute) . In theAuthorizeCore override, implement your custom authorization logic, taking the user inHttpContext.Current.User.Identity.Name and the roles defined in the Roles property of the AuthorizeAttribute base class. Note you can also define properties on your custom authorization attribute and use that in your authorization logic. For example you can define a property representing roles as enumerated values specific to your app, instead of using the Roles property which is just a string.

  3. Affix your controllers and actions with your custom authorize attribute, instead of the default Authorize attribute.

     

我看了感觉很受启发,但却不太清楚如何重载AuthorizeAttribute的AuthorizeCore方法。为此我做了个Demo:

 

1. 使用VS2010建立一个ASP.NET MVC2 Web工程Aut,在Model目录下新建一个MyAuthAttribute类,如下:

[c-sharp]  view plain copy print ?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. namespace AuthTest.Models  
  7. {  
  8.     public class MyAuthAttribute : AuthorizeAttribute  
  9.     {  
  10.         // 只需重载此方法,模拟自定义的角色授权机制  
  11.         protected override bool AuthorizeCore(HttpContextBase httpContext)  
  12.         {  
  13.             string currentRole = GetRole(httpContext.User.Identity.Name);  
  14.             if(Roles.Contains(currentRole ) )  
  15.                 return true;  
  16.             return base.AuthorizeCore(httpContext);  
  17.         }  
  18.   
  19.         // 返回用户对应的角色, 在实际中, 可以从SQL数据库中读取用户的角色信息  
  20.         private string GetRole(string name)  
  21.         {  
  22.             switch(name)  
  23.             {  
  24.                 case "aaa":  return "User";  
  25.                 case "bbb"return "Admin";  
  26.                 case "ccc"return "God";  
  27.                 defaultreturn "Fool";  
  28.             }  
  29.         }  
  30.     }  
  31.   
  32. }  

 

2. 修改HomeController, 如下

[c-sharp]  view plain copy print ?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. using System.Web.Security;  
  7. using AuthTest.Models;  
  8. namespace AuthTest.Controllers  
  9. {  
  10.     [HandleError]  
  11.     public class HomeController : Controller  
  12.     {  
  13.         public ActionResult Index()  
  14.         {  
  15.             ViewData["Message"] = "欢迎使用 ASP.NET MVC!";  
  16.             // 模拟用户成功登录  
  17.             FormsAuthentication.SetAuthCookie("aaa"false);  
  18.             return View();  
  19.         }  
  20.   
  21.         // 验证我们自定义的AuthorizeAttribute是否起作用,   
  22.          // 此Action只能由角色为“God”的用户访问  
  23.         [MyAuth(Roles="God")]  
  24.         public ActionResult About()  
  25.         {  
  26.             return View();  
  27.         }  
  28.     }  
  29. }  

3. 按F5调试,再点击页面上的“关于”链接,哈哈,知道了吧?

你可能感兴趣的:(在ASP.NET MVC2中使用自定义的AuthorizeAttribute绕过内置的Membership/Role机制)