Enforce security check in ASP.NET MVC?
I am implementing a collaborative web gallery, and I have a few roles for each user:
- Admin
- DeleteImage
- DeleteOwnImage
- etc..
For any controller-action, we can apply [Authorize] tag to them plus which roles we want to allow, right? It is fine for Admin/DeleteImage since these two are global; but my question is, like DeleteOwnImage is kind of contextual, in order to determine whether it is valid开发者_如何学Go, we need:
- To know what image it is trying to delete (from request)
- Retrieve the owner of that image (from service or repository)
- Compare current user = that owner
Obviously [Authorize] is not enough to do so, but is it possible to do that on custom ActionFilters? Any hint?
Yes, this is possible with a custom action filter. You can extend from AuthorizeAttribute
, the most basic implementation being something like:
public class OwnImageAuthorizeAttribute : AuthorizeAttribute {
public string ImageIdKey { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext) {
bool authorized = false;
// Get the current user
var currentUser = ...;
// Get the image ID, whether it is in the route or querystring
int imageId
if(int.TryParse(httpContext.RouteData.Values(ImageIdKey), out imageId)) {
// From querystring: httpContext.Request.Querystring[ImageIdKey]
// Authorize the user
authorized = YourMethodToCheckIfUserIsOwner(currentUser, imageId);
}
return authorized;
}
Then, decorate your method:
[OwnImageAuthorize(ImageIdKey = "imageId")]
public ActionResult MyAction() { }
You can find some more details here.
You can easily add something like this in an ActionFilter, Just add an action filter with OnActionExecuting implemented.
Although, depending on your DB schema this could be achieved on the DB level with your query. You could just delete when owner equals recieved recieved id. (I mean, inside the action method and not in the filter)
EDIT: If you're using some kind of IOC container for the repositories, you should look around for the new IOC features in MVC3 (if you're using MVC3) to inject dependencies into your action filters.
http://bradwilson.typepad.com/blog/2010/07/service-location-pt4-filters.html
EDIT2:
BTW, I myself don't really like doing too much business logic in ActionFilters, especially involving calls to the DB. Even more when it's something very specific that'll be used for one action.
精彩评论