应用程序允许用户创建记录。为了我们的目的,让我们称这些记录为目标。
一个用户不应该看到其他用户创建的目标。
阻止UserA访问UserB目标的最佳方法是什么?
我可以这样做:
//using asp.net membership
Guid uId = (Guid)System.Web.Security.Membership.GetUser().ProviderUserKey;
//goal records contain a foreign key to users, so I know who owns what
Goal theGoal = db.Goals.SingleOrDefault(g => g.GoalId == goalId
&& g.UserId == uId);
if (null == theGoal)
{
ViewData["error"] = "Can't find that goal.";
return View("Error");
}
else
{
return View(theGoal);
}
这很好用。问题是我在访问目标的每个操作中都有类似的代码。
是否有更可重用的方法来实现这一目标?
我想把它作为授权过滤器实现。该计划存在两个问题:
1)要求过滤器了解并使用DB 2)需要2个查询(过滤器中为1,操作中为另一个)而不是我现在的操作中的1个查询。
有什么更干嘛的方法来实现这个目标?
答案 0 :(得分:2)
自定义模型绑定器是执行此操作的好地方:
public class GoalModelBinder : DefaultModelBinder
{
private readonly IGoalRepository _repository;
public GoalModelBinder(IGoalRepository repository)
{
_repository = repository;
}
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
// Here the default model binder does his job of binding stuff
// like the goal id which you would use in the repository to check
var goal = base.CreateModel(controllerContext, bindingContext, modelType) as Goal;
var user = controllerContext.HttpContext.User;
var theGoal = _repository.GetGoal(user, goal);
if (theGoal == null)
{
throw new HttpException(403, "Not authorized");
}
// It's OK, we've checked that the Goal belongs to the user
// => return it
return theGoal;
}
}
然后在Application_Start
注册此模型绑定器:
// some implementation of your repo
var sqlRepo = new SqlGoalRepository();
ModelBinders.Binders.Add(typeof(Goal), new GoalModelBinder(sqlRepo));
现在你的控制器动作变得不那么乱了:
[Authorize]
public ActionResult Edit(Goal goal)
{
// if we get that far we are fine => we've got our goal
// and we are sure that it belongs to the currently logged user
return View(goal);
}