简体   繁体   中英

ASP.NET MVC - Limit what users can view/edit

We're working on an ASP.NET MVC 5 app in Visual Studio 2015 Update 3. Users are already being authenticated via Identity Framework and we're using authorization to limit who can access which controllers/actions. However, we now need something more fine-grained: On the actions, we need to limit what records a user can view and edit.

For example, a user goes to the GET version of MyController/Edit/5 , we only want this user to be able to fetch items s/he has access to based on some rules, and not view records from other users by simply changing the URL to MyController/Edit/9999 (changing the ID in this case). In some cases, the rules are more complex, so it's not always the ID. And the same rules apply to POST actions.

We're using view models (VMs) to send and receive data to/from views. So one VM might be ItemVm . We want that customer to only be able to have access to their own ItemVm s and not other users'. Here's a sample from a controller:

public async Task<ActionResult> Edit(int id)
{   
    // Only allow users to see "items" they have access to 
    // based on custom rules. If they enter a different ID,
    // prevent them from viewing/editing that information.
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(ItemVm itemVm){
    // Only allow users to edit their own "items".
}

This article talks about locking down based on resources, but wasn't sure if that's what is needed in this case. Would we do this via a custom authorize attribute? If so, how do you pass in the ItemVm and apply your rules? Of course, it's possible to add a check inside each and every action before proceeding; is there a best-practices way?

Your help is much appreciated. Thanks.

The specifics would change, but might look something like this:

public async Task<ActionResult> Edit(int id)
{   
  // Only allow users to see "items" they have access to 
  // based on custom rules. If they enter a different ID,
  // prevent them from viewing/editing that information.
  string userId = User.Identity.GetUserId();
  var items = context.Items.Where(m => m.Userid == userId);
  return View(items);
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(ItemVm itemVm){
  // Only allow users to edit their own "items".
  string userId = User.Identity.GetUserId();
  var item = context.Items.Where(m => m.Id == itemVm.ItemId && m.UserId == userId);
  if (item != null)
  {
    //update item stuff
  }
  return View();
}

Focusing on your last paragraph.

This article talks about locking down based on resources, but wasn't sure if that's what is needed in this case.

If your project is built using .NET core, then yes. Otherwise your project is built using .NET framework, which means the article is irrelevant.

Would we do this via a custom authorize attribute? If so, how do you pass in the ItemVm and apply your rules?

Assuming a .NET core project: A custom authorize attribute is not needed. Instead, you'll inject the IAuthorizationService dependency into the Controller ( the article and this video (start at around 27:00) will have a lot more information)

Of course, it's possible to add a check inside each and every action before proceeding; is there a best-practices way?

Not sure what the best-practice would be, but I would create a parent controller which has a method for authorizing resources based on the current user.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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