如果move.UserId不等于currentUserId,则尝试构建异常,然后重定向到Action,如果move.UserId等于currentUserId则返回View。
请参阅此处的代码:
public ActionResult Details(int id)
{
MembershipUser currentUser = Membership.GetUser();
Guid currentUserId = (Guid)currentUser.ProviderUserKey;
Move move = db.Moves.Where(m => m.UserId == currentUserId)
.FirstOrDefault();
if (currentUser != null && currentUser.ProviderUserKey != null && currentUser.IsApproved)
{
if (move.UserId == currentUserId)
{
return View(move);
}
}
return RedirectToAction("Oops", new RouteValueDictionary(
new { controller = "Account", action = "Oops", area = "", id = UrlParameter.Optional }));
}
我想把它绑定到将带回Move /(int)的url,这样如果用户将其修改为返回move.UserId!= currentUserId的移动的(int),那么它们也会重定向。目前,他们可以修改Url以获取其他人的动作。
public ViewResult Index()
{
if (User.Identity.IsAuthenticated)
{
MembershipUser currentUser = Membership.GetUser();
Guid currentUserId = (Guid)currentUser.ProviderUserKey;
if (currentUser != null && currentUser.ProviderUserKey != null && currentUser.IsApproved)
{
var results = db.Moves.Where(move => move.UserId == currentUserId)
.ToList();
return View(results);
}
}
return View(db.Moves.ToList());
}
[ClientValidation]
public ActionResult Details(Move move)
{
return View(move);
}
@model MovinMyStuff.Domain.Entities.Move
@{
ViewBag.Title = "Details";
}
<div>
@Html.DisplayFor(model => model.StartCity),
@Html.DisplayFor(model => model.StartState)
@Html.DisplayFor(model => model.StartZip) -
@Html.DisplayFor(model => model.EndCity),
@Html.DisplayFor(model => model.EndState)
@Html.DisplayFor(model => model.EndZip)
</div>
<fieldset>
<div class="job-details">
@Html.HiddenFor(model => model.MoveId)
@Html.HiddenFor(model => model.UserId)
<ul class="distance">
<li>
<div>
Distance</div>
</li>
<li>1,978.6 Miles</li>
</ul>
<ul class="address-wrapper">
<li>
<ul class="address from">
<li>
<div>
From</div>
</li>
<li><span>Address: </span>
@Html.DisplayFor(model => model.StartStreetNumber)
@Html.DisplayFor(model => model.StartStreetName)
</li>
...
</fieldset>
答案 0 :(得分:1)
要测试的第一件事是LINQ查询是否返回了Move。如果不是,则表示用户正在尝试显示不属于他的移动,因为在您的查询中,您有一个.Where
子句限制当前用户仅移动。
现在你将得到一个NullReferenceException。
所以:
[Authorize]
public ActionResult Details(int id)
{
MembershipUser currentUser = Membership.GetUser();
Guid currentUserId = (Guid)currentUser.ProviderUserKey;
Move move = db.Moves.Where(m => m.UserId == currentUserId && m.MoveId == id).FirstOrDefault();
if (!currentUser.IsApproved || move == null)
{
// the user is trying to display a move that doesn't belong to him =>
// redirect him or throw a 403 HTTP exception
return RedirectToAction("Oops", new RouteValueDictionary(new { controller = "Account", action = "Oops", area = "", id = UrlParameter.Optional }));
}
// at this stage we can grant access to the user because we know
// that he is authenticated, he is approved and that the move he is
// trying to consult belongs to him
return View(move);
}
显然,如果您需要在许多控制器操作中重复此逻辑,则值得编写自定义Authorize属性:
[EnsureUserAllowedToConsultMove]
public ActionResult Details(Move move)
{
// at this stage we can grant access to the user because we know
// that he is authenticated, he is approved and that the move he is
// trying to consult belongs to him
return View(move);
}
以下是此自定义Authorize属性的外观:
public class EnsureUserAllowedToConsultMoveAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
if (!httpContext.Request.RequestContext.RouteData.Values.ContainsKey("id"))
{
return false;
}
var id = (string)httpContext.Request.RequestContext.RouteData.Values["id"];
var currentUser = Membership.GetUser();
var currentUserId = (Guid)currentUser.ProviderUserKey;
return db.Moves.Any(m => m.UserId == currentUserId && m.MoveId == id);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
var values = new RouteValueDictionary(new
{
controller = "account",
action = "oops",
area = ""
});
filterContext.Result = new RedirectToRouteResult(values);
}
}
现在,您已设法将关注点分开,并将授权逻辑外部化为自定义授权属性。您的控制器不再需要使用此类代码进行污染。
答案 1 :(得分:0)
您应该使用“授权”过滤器进行此类工作。请查看此更多信息ASP.NET MVC Custom Authorization