我正在编写一个具有相对复杂数据模型的MVC 5应用程序。
我有列表和列表与相关的相册。
为了开始,我只是确保当用户试图调用控制器的Edit函数时,该用户是该对象的所有者。像这样:
// Listing Controller
public bool VerifyOwnership(int? id)
{
if (id == null) return false;
Listing listingModel = db.Listings.Find(id);
if (listingModel == null)
{
return false;
}
else
{
return User.Identity.GetUserId() == listingModel.SellerID;
}
}
但是,此检查现在在我的代码库中传播。由于相册属于商家信息,因此此代码对我来说似乎可怕:
// AlbumController
public ActionResult Edit(int? id, int listingId)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Album a = db.Albums.Find(id);
if (a == null)
{
return HttpNotFound();
}
var l = new ListingController();
if (!l.VerifyOwnership(listingId))
return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
ViewBag.ListingID = listingId;
return View(a);
}
我认为我这样做错误。
理想情况下,Album控制器不会仅仅为了检查所有权而实例化ListingController。我可以将所有权逻辑从ListingController中复制出来并粘贴到AlbumController中,但现在我要复制粘贴代码。呸。
我读了这篇关于创建自定义Authorize属性的文章 - ASP.NET MVC Attribute to only let user edit his/her own content,除了我不确定如何在AuthorizeCore覆盖中实例化ApplicationDbContext对象以便我可以查找所有者之外,这似乎没问题。上市并做我的检查。可以毫不费力地创建ApplicationDbContext对象吗?它们是与持久性数据库连接相关还是抽象的?
答案 0 :(得分:0)
这是你出错的地方......
Album a = db.Albums.Find(id);
我可以输入任何ID,您的应用会去取得它,然后执行不需要的所有权验证......
从另一端解决问题,如果我们根据用户首先访问的内容确定结果的范围,然后在用户有权访问的范围内搜索相册,该怎么办?以下是一些例子,让您了解我的意思。
db.Users.Where(user => user.Id == this.CallerId)
.SelectMany(user => user.Albums)
.Where(album => album.Id == "foo");
db.Albums.Where(album => album.OwnerId == this.CallerId)
.Where(album => album.Id == "bar");
这一切都将归结为数据库的布局以及映射实体模型的方式,但概念是相同的。