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

时间:2012-06-14 16:17:15

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

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

4 个答案:

答案 0 :(得分:28)

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

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
}

答案 1 :(得分:1)

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

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

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

这也可以让你以后具有灵活性,允许管理员用户

答案 2 :(得分:0)

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

答案 3 :(得分:-1)

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