【问题标题】:ASP.NET MVC Attribute to only let user edit his/her own contentASP.NET MVC 属性只允许用户编辑他/她自己的内容
【发布时间】:2012-06-14 16:17:14
【问题描述】:

我有一个名为 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] 属性或其他一些机制来使代码更清晰。

【问题讨论】:

    标签: c# .net asp.net-mvc security authentication


    【解决方案1】:

    是的,您可以通过自定义 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
    }
    

    【讨论】:

    • 谢谢!我将使它更通用。就像提交实现了一个名为 IUserOwnable 的接口,它有一个 UserID。然后将存储库传递到获取 IUserOwnable 并将用户的 UserID 与 IUserOwnable 的 UserID 进行比较的属性中
    • 当然,这可以根据您的具体要求进行通用。
    • 不错的方法。我希望到现在它会有一个内置属性
    • 你将如何缓存它,这样它就不需要在每次有这个特定的 submit_id 和 user_id 的授权属性时检查数据库? @DarinDimitrov
    • @DarinDimitrov 在使用基于 JWT 令牌的身份验证的 Web API 中执行此 .net 核心的最佳方法是什么?
    【解决方案2】:

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

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

    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);
         }
    }
    

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

    【讨论】:

      【解决方案3】:
      @if (Request.IsAuthenticated && User.IsInRole("Student"))
          {
          @Html.ActionLink("Edit", "Edit", new { id = item.StdID })
          }
      

      就我而言,登录用户是学生。所以我说如果登录请求通过了身份验证,并且他的角色是学生,那么让他可以访问编辑链接。

      下面这允许您让普通用户或管理员也执行编辑。

      @if(Request.IsAuthenticated && User.IsInRole("Student") || 
      User.IsInRole("Administrator"))
      {
       @Html.ActionLink("Edit", "Edit", new { id = item.StdID })
      }
      

      【讨论】:

        【解决方案4】:

        我建议阅读AuthorizeAttribute(请参阅here)。另外,你看过this 的帖子吗?它介绍了如何覆盖身份验证属性内部以及如何使用 IPrincipal 和 IIdentity。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-21
          • 1970-01-01
          • 1970-01-01
          • 2014-12-14
          相关资源
          最近更新 更多