ASP.NET MVC Attribute只允许用户编辑他/她自己的内容怎么办?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (23)

我有一个控制器方法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
}
用户回答回答于

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

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

这也可以让你稍后有灵活性来允许管理员用户这样的事情

扫码关注云+社区