模型所有权检查

mat*_*tt. 12 asp.net-mvc entity-framework asp.net-mvc-4

在模型被修改(更新或删除)之前的我的控制器中,我试图验证执行操作的用户实际上拥有他们试图修改的对象.

我目前正在方法级别执行此操作,似乎有点多余.

[HttpPost]
public ActionResult Edit(Notebook notebook)
{
    if (notebook.UserProfileId != WebSecurity.CurrentUserId) { return HttpNotFound(); }

    if (ModelState.IsValid)
    {
        db.Entry(notebook).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(notebook);
}
Run Code Online (Sandbox Code Playgroud)

是否存在可以在各种模型中重复使用的通用方法?

有可能用这个ActionFilter吗?

Ode*_*ode 5

过滤方法可能如下所示:

public class VerifyOwnership : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        foreach(var parameter in filterContext.ActionParameters)
        {
            var owned  = paramter.Value as IHaveAnOwner;
            if(owned != null)
            {                    
                if(owned.OwnerId != WebSecurity.CurrentUserId)
                {
                    // ... not found or access denied
                }
            }
        }
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

假设像Notebook这样的模型实现了特定的接口.

public interface IHaveAnOwner
{
    int OwnerId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Blowdart有一个很好的观点,即用户可以在帖子中篡改OwnerId.我相信他们也可以篡改他们的身份证,但他们必须知道其他用户的票并且篡改两者以获得与其他用户匹配的ID,我相信.


blo*_*art 3

我可以看到您所拥有的一个问题 - 您依赖用户输入来执行安全检查。

考虑你的代码

if (notebook.UserProfileId != WebSecurity.CurrentUserId)
Run Code Online (Sandbox Code Playgroud)

Notebook源自模型绑定。所以 UserProfileId 来自模型绑定。你可以很高兴地伪造这一点 - 例如,我使用 Firefox 的 TamperData 来更改隐藏的 UserProfileId 的值,以匹配我的登录信息,然后我就离开了。

我最终要做的(在服务中,而不是在控制器中)是根据传递的唯一 ID 从数据库中拉回记录(例如 Edit/2 将使用 2),然后检查 User.Identity。针对我返回的数据库记录中的当前所有者字段的名称(好吧,传递的身份参数)。

因为我从数据库(存储库,无论什么)中撤回,属性对此不起作用,而且我不确定属性的方法是否足够通用。