.NET custom authorize attribute (mvc) - asp.net-mvc

In certain Controller I have CRUD methods. In order to access these methods user needs to be logged in. This is why I used [Authorize] attribute for this controller. Now I need additional attribute which would check if item that user wants to view/delete/update belongs to him.
Is it possible and recommended to do this with attribute or you would suggest using check methods inside each method? If you suggest using attribute, could you please provide me some links/instructions?
EDIT:
Ofcourse, if attribute returns false than I don't want to redirect user to login page but show him an error message...

It can be done with a custom Authorize attribute, but it's much cleaner to put the logic inside your controller methods.

The attribute is related to the action being called (the controller class method). On that basis any attribute relating to the user's ownership of the object being manipulated (from your Model) should really be on the entity/class that the user is attempting to manipulate. You'll probably find it easier to validate the user within the Model method rather than using an attribute to achieve this.

In my opinion it is possible, just google for 'Custom Authorize Attribute'.
But maybe it is better to query your database with something like this:
ContextOrSession.Query<Something>.Where(Something.Groups.Intersect(User.Groups).Count>0)

Related

ActionFilter or RenderAction in ASP.NET MVC?

I'm working on an ASP.NET MVC controller with several action methods, all of which need the same bit of data. This data requires a lookup that can only be done with the route values (so, I can't do the lookup in the constructor). I'm sure this has been discussed at length, but I've yet to find a satisfactory recommendation.
What's the best way to get this data without repeating myself in each action method? I'm working through:
Create an Action Filter, this seems like the best bet, but where do I store the object, in the action parameters? Is it appropriate to create a ViewModel object in an action filter and pass it directly to the action methods, for them to fill out the rest of the ViewModel object?
Create a child action (Html.RenderAction) to render this data, but this requires a second set of lookups since the child action requires another full cycle of instantiating the controller.
Helper method/property called in each action method.
Thought or opinions on a best approach here?
A filter is probably your best bet and you can store the object in ViewData.
Another option (not a better one) is to create your own controller base class that overrides the ExecuteCore method and does the lookup there.
I did this for logging since I want to log each page view and I didn't want to have to add a filter to each and every controller I made. In mvc 3 there will be a way to declare global filters which can fix this as well.
Ok, so given what you've told me, I would suggest using a custom ModelBinder.
It's the best fit for the situation. I would argue that using a filter is the wrong approach because a filter's job isn't to bind data - that's a job for a ModelBinder.
HTHs,
Charles
EDIT: I've just been thinking about it and I'm a little bit torn if you should use a model binder or not.
The general rule of thumb I just came up with is that if you need the ProjectDetails inside the action itself, use a ModelBinder but if you don't need the ProjectDetails inside the action, use an ActionFilter to just add it to your model / viewdata.
Maybe someone else could throw their 2c in.
You could override the OnActionExecuting() method in your controller and get the data there.

I need to re route action based on some criteria

If a user is logged in and the ChangePasswordRequired flag is set, i need to disregard the current action and redirect them to the ChangePassword action.
In other words, I do not want the user to be able to do anything until he or she changes his or her password.
Which method should my base controller override and how should I handle the redirect?
You should create your own action filter.
The exact type of action filter you want to use is one that implements IAuthorizationFilter and the method you want to use it the OnAuthorizing() or close. This filter type is executed before all the others.
Instead of the [Authorize] filter you would use your own filter. Be sure to make your flag check and whether the user is authenticated (Request.IsAuthenticated)
Kindness,
Dan
I would use an actionfilter that you add to every controller class that should implement this behaviour. You can read some more on at this blog post by Phil Haack

Accessing Controller Properties from a View

I have a User object on a Base controller, this is the standard type of User object you have with the .Net Membership Provider. I need this is decide if users have access to actions, views, and so on.
I am having a problem whereby I want to display user information on the Masterpage. Like a login view from WebForms. I tried to access the User object from the Masterpage but I can't.
So:
Am I breaking the separation of concerns by checking if the user is logged in on the view (simple if statement which changes what is displayed).
Can I simply access the base controller namespace to access this property or is there something wrong with that? When do the controllers get initialised?
As I write this I consider that having my base controller have this property might be a bad idea on the first place.
AGHH!! How would you handle checking user information to change the Masterpage.
Use this:
<% var user = ViewContext.HttpContext.User; %>

Is it possible to override an attribute which has been applied at controller level on a specific method?

If I've applied an authorisation attribute at controller level, is it possible to override this on one of the methods on that controller?
Thanks
James
That depends upon what kind of "override" you want. You cannot remove the attribute which is on the class, but you can add the attribute to the method again in order to make things more restrictive.
Update in response to comments. First, making your own AuthorizeAttribute is somewhat dangerous. AuthorizeAttribute contains code which interacts with the caching attributes in order to ensure that the cache cannot serve protected content to a non-authorized user. At a minimum, you should subtype the existing AuthorizeAttribute rather than creating something wholly new. Generally, however, it's a better idea to use the existing AuthorizeAttribute and specialize your authorization by creating a new/finding an existing ASP.NET membership provider.
I don't think it would be good design to have a filter on an action which "overrides" a filter on a controller. However, you could change the design of the filter on the controller to not require authorization on an action of a certain name. You could, for example, override the AuthorizeAttribute.AuthorizeCore method to test for an action name in the same way the existing method tests for the user name and the roles. Take very careful note of the comments in this method regarding thread safety.
I'm not sure if this is exactly the same question, but it may help...
How to make ActionFilter on action method take precedence over same ActionFilter on controller

asp.net mvc newbie question

I recently started to look into asp.net mvc. Here is my issue.
Say every page on an application needs a variable set by the user, e.g. a date. If the user starts from url I provide, it is all good as I ask for that date and save it for the session. How can I redirect the user to the first page if they save the some other url (to a different controller and action).
In other words, I guess I am looking for something like [Authorize] attribute but on an application level.
Thanks for any help.
I would probably create a base controller that all of my controllers derive from. In the base controller I'd override the OnActionExecuting method to check the session for the required variable. If the variable isn't present, I would set the ActionExecutingContext Result property to a RedirectToRouteResult to the appropriate controller/action to set the variable.
Another alternative is to create a custom FilterAttribute that you decorate the appropriate controllers/actions with that does basically the same thing. I would only do this if the filter was to apply only to certain controllers or actions and not all as you describe in your question.

Resources