使用基于声明的模型设计ASP.Net MVC应用程序授权.让我们说我们有一个名为 – Product的对象.通常,有4种不同的操作 – 创建,编辑,删除和查看.授权使用ClaimsAuthorize属性完成.
- [Authorize]
- public class ProductController : Controller
- {
- [ClaimsAuthorize("Product","VIEW")]
- public List<Product> GetProducts()
- {
- // ....
- }
- [ClaimsAuthorize("Product","CREATE")]
- public Product CreateNewProduct(Product product)
- {
- //....
- }
- }
但就我而言,我必须支持不同类型的EDIT权限:
>如果同一用户最初创建了产品,则某些用户可以编辑产品
>如果产品属于特定类别,并且用户也可以访问同一类别,则某些用户可以编辑产品
>有些用户可以编辑所有产品(这是正常的产品编辑操作)
如何优雅地授权所有这些Edit操作(最好是如上所示的属性驱动),同时我希望将授权代码与普通的MVC控制器代码和业务逻辑分开.
[上面的代码示例在语法上不正确,我只是为了解释这个问题而编写的]
让我知道你的想法.
解决方法
对于你的问题的第一部分,基于声明的授权,我已经在
this similar question回答了它.我不打算在此重复.
但是对于您的另一个规则,例如只有所有者可编辑的产品.您可以为每个规则编写单独的AuthorizeAttribute并将其应用于您的操作,将此视为一个简单示例:
- using Microsoft.AspNet.Identity;
- public class OwnerAuthorizeAttribute : AuthorizeAttribute
- {
- private string _keyName;
- public bool IsPost { get; set; }
- public OwnerAuthorizeAttribute(string keyName)
- {
- _keyName = keyName;
- }
- protected override bool AuthorizeCore(HttpContextBase httpContext)
- {
- // imagine you have a service which could check owner of
- // product based on userID and ProductID
- return httpContext.User.Identity.IsAuthenticated
- && this.ContainsKey
- && _productService.IsOwner(httpContext.User.Identity.GetUserId(),int.Parse(this.KeyValue.ToString()));
- }
- private bool ContainsKey
- {
- get
- {
- return IsPost
- ? HttpContext.Current.Request.Form.AllKeys.Contains(_keyName)
- // for simplicity I just check route data
- // in real world you might need to check query string too
- : ((MvcHandler)HttpContext.Current.Handler).RequestContext
- .RouteData.Values.ContainsKey(_keyName);
- }
- }
- private object KeyValue
- {
- get
- {
- return IsPost
- ? HttpContext.Current.Request.Form[_keyName]
- // for simplicity I just check route data
- // in real world you might need to check query string too
- : ((MvcHandler)HttpContext.Current.Handler)
- .RequestContext.RouteData.Values[_keyName];
- }
- }
- }
您也可以对其他规则重复相同的模式.
- [OwnerAuthorize("id")]
- public ActionResult Edit(int id)
- {
- // your code
- }
- [HttpPost]
- // double checking in post back too
- [OwnerAuthorize("id",IsPost = true)]
- public ActionResult Edit(Product product)
- {
- // your code
- }
很明显,您可以将多个AuthorizeAttribute应用于您的操作.在这种情况下,所有这些都必须返回true.
- [ClaimsAuthorize("Product","EDIT")]
- [OwnerAuthorize("id")]
- [YetOtherAuthorize]
- public ActionResult MyFancyAction(int id)
- {
- }