如何为以下情况实现自定义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 }
这具有以下优点:
- 没有人会稍后想知道它在哪里被使用。
- 没有其他地方无法使用的类(您没有使用自定义属性重用)
- 性能更好:单次获取Post
- 人们更容易阅读/弄清楚它是如何工作的。 没有魔法代码可以追踪。
- 多年以后,当HttpContextBase类不存在,或用于获取Id参数的技巧的其他部分都消失了,代码仍然有效……