ASP.NET MVC属性只允许用户编辑他/她自己的内容

我有一个名为Edit的控制器方法,用户可以在其中编辑他们创建的数据,如此…

 public ActionResult Edit(int id) { Submission submission = unit.SubmissionRepository.GetByID(id); User user = unit.UserRepository.GetByUsername(User.Identity.Name); //Make sure the submission belongs to the user if (submission.UserID != user.UserID) { throw new SecurityException("Unauthorized access!"); } //Carry out method } 

这种方法工作正常但是放入每个控制器的Edit方法都有点乱。 每个表都有一个UserID所以我想知道是否有一种更简单的方法可以通过[Authorize]属性或其他一些机制使代码更清晰自动化。

是的,您可以通过自定义Authorize属性实现此目的:

 public class MyAuthorizeAttribute : AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { var authorized = base.AuthorizeCore(httpContext); if (!authorized) { return false; } var rd = httpContext.Request.RequestContext.RouteData; var id = rd.Values["id"]; var userName = httpContext.User.Identity.Name; Submission submission = unit.SubmissionRepository.GetByID(id); User user = unit.UserRepository.GetByUsername(userName); return submission.UserID == user.UserID; } } 

然后:

 [MyAuthorize] public ActionResult Edit(int id) { // Carry out method } 

我们假设您需要将我们提取的提交实例作为操作参数提供给自定义属性,以避免再次访问数据库,您可以执行以下操作:

 public class MyAuthorizeAttribute : AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { var authorized = base.AuthorizeCore(httpContext); if (!authorized) { return false; } var rd = httpContext.Request.RequestContext.RouteData; var id = rd.Values["id"]; var userName = httpContext.User.Identity.Name; Submission submission = unit.SubmissionRepository.GetByID(id); User user = unit.UserRepository.GetByUsername(userName); rd.Values["model"] = submission; return submission.UserID == user.UserID; } } 

然后:

 [MyAuthorize] public ActionResult Edit(Submission model) { // Carry out method } 

我建议你从动作/控制器中拉出逻辑并构建一个域类来处理该逻辑。

操作方法实际上应该只处理从视图中获取数据和向视图发送数据。 您可以创建足够通用的东西来满足您的需求,但也会遵循单一责任主体。

 public class AuthorizedToEdit { protected override bool AuthorizeCore(string user, int itemId) { var userName = httpContext.User.Identity.Name; var authUsers = SubmissionRepository.GetAuthoriedUsers(itemId); return authUsers.Contains(user); } } 

这也可以让您以后具有灵活性,允许管理员用户之类的东西

我建议阅读AuthorizeAttribute (见这里 )。 另外,你看过这篇文章吗? 它讨论了如何覆盖认证属性内部以及如何使用IPrincipal和IIdentity。