如何为以下情况实现自定义Authorize属性?

所以我有我的行动方法

[Authorize(Roles="Admin")] public ActionResult EditPosts(int id) { return View(); } 

在我的情况下,我需要授权管理员,以便他们可以编辑post,但(这里是很酷的部分),我还需要允许post的创建者能够编辑一个普通用户的post。 那么我怎样才能过滤掉创建post的用户以及管理员,但是其他人是否未经授权? 我接受PostEntry id作为路由参数,但是在atribute之后,属性只接受常量参数,看起来非常困难,你的答案非常受欢迎,干杯!

您可以编写自定义授权属性:

 public class AuthorizeAdminOrOwnerOfPostAttribute : AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { var authorized = base.AuthorizeCore(httpContext); if (!authorized) { // The user is not authenticated return false; } var user = httpContext.User; if (user.IsInRole("Admin")) { // Administrator => let him in return true; } var rd = httpContext.Request.RequestContext.RouteData; var id = rd.Values["id"] as string; if (string.IsNullOrEmpty(id)) { // No id was specified => we do not allow access return false; } return IsOwnerOfPost(user.Identity.Name, id); } private bool IsOwnerOfPost(string username, string postId) { // TODO: you know what to do here throw new NotImplementedException(); } } 

然后用它装饰你的控制器动作:

 [AuthorizeAdminOrOwnerOfPost] public ActionResult EditPosts(int id) { return View(); } 

我知道你已经接受了一个答案,这已经发布了一段时间..(顺便说一句:添加自定义属性的优秀答案),但我会指出以下内容:

如果您使用此属性一次。 在单一方法上。 这不是一个好的实现。 相反,你应该:

 [Authorize] // Just make sure they are auth'ed at all. public ActionResult EditPosts(int id) { Post SomePost = findPostByID (id); // However you do it - single lookup of post if (!user.IsInRole("Admin") && !{IsOwnerOfPost(post)} ) Return Not Authorized ... Edit post code here } 

这具有以下优点:

  1. 没有人会稍后想知道它在哪里被使用。
  2. 没有其他地方无法使用的类(您没有使用自定义属性重用)
  3. 性能更好:单次获取Post
  4. 人们更容易阅读/弄清楚它是如何工作的。 没有魔法代码可以追踪。
  5. 多年以后,当HttpContextBase类不存在,或用于获取Id参数的技巧的其他部分都消失了,代码仍然有效……