简体   繁体   English

MVC-仅允许用户编辑自己的数据

[英]MVC - Only allow users to edit their own data

I am writing an MVC 5 app with a relatively complicated data model. 我正在编写一个具有相对复杂的数据模型的MVC 5应用程序。

I have Listings and Listings have photo Albums associated with them. 我有列表,并且列表有与之相关的相册。

To get things started, I just made sure that when a user is trying to call the Edit function of a controller, that the user was the owner of the object. 首先,我只是确保当用户尝试调用控制器的Edit函数时,该用户是对象的所有者。 Like so: 像这样:

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

However, this check is now propagating itself throughout my code base. 但是,此检查现在正在整个代码库中传播。 Since Albums are owned by Listings, this code didn't seem that terrible to me: 由于相册归清单所有,因此对我而言,这段代码并不那么糟糕

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

I think I'm doing it wrong . 我想我做错了

It seems that ideally the Album controller would not be instantiating a ListingController just to check ownership. 理想情况下,专辑控制器似乎不会为检查所有权而实例化ListingController。 I could copy the ownership logic out of the ListingController and paste it into the AlbumController, but now I'm copy pasting code. 我可以从ListingController中复制所有权逻辑,然后将其粘贴到AlbumController中,但是现在我要复制粘贴代码。 Yuck. uck

I read this article about making a custom Authorize attribute - ASP.NET MVC Attribute to only let user edit his/her own content , which seems ok except that I wasn't sure how to instantiate an ApplicationDbContext object inside the AuthorizeCore override so that I could lookup the owner of the listing and do my checks. 我阅读了有关创建自定义Authorize属性-ASP.NET MVC属性的文章,该属性只允许用户编辑自己的内容 ,这看起来还可以,只是我不确定如何在AuthorizeCore覆盖内实例化ApplicationDbContext对象,以便我可以查找列表的所有者并进行我的检查。 Is it ok to just create ApplicationDbContext objects willy-nilly? 可以随意创建ApplicationDbContext对象吗? Do they correlate to persistent database connections or are they an abstraction? 它们与持久数据库连接相关还是抽象?

This is where you're going wrong.... 这就是您要出问题的地方...

 Album a = db.Albums.Find(id);

I could have typed in any ID and your app would go and fetch it and then perform a ownership verification which is unneeded... 我可以输入任何ID,然后您的应用会去取它,然后执行不需要的所有权验证...

Tackle the problem from the other end, what if, we were to scope our results by what the users has access to first, and then performing a search for an album within the scope of what the user has access to. 从另一端解决问题,如果要解决的话,我们首先要根据用户可以访问的范围来确定结果的范围,然后在用户可以访问的范围内进行搜索。 Here's a few examples to give you an idea of what I mean. 这里有一些例子可以让您了解我的意思。

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

It's all going to come down to the layout of your db and the fashion in which you've mapped your entity models, but the concept is the same. 一切都取决于数据库的布局以及映射实体模型的方式,但是概念是相同的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM