I'm wanting to require that all users have some additional information filled out before they proceed to ANY section of the site that requires authentication.
If possibly I'm wanting to catch on [Authorize] annotations, but ignore any #User.IsInRole("something")
Is there a method that I can override in Global.asax or ?
I'm only hoping to grab the annotations because my only use for .IsInRole() is to display different info to them and I want the links there so they actually see what is needed to get to the annotations. Hope this makes sense (kinda tired).
You can override the AuthorizeAttribute itself; that'll give you access to the OnActionExecuting() method that gets fired when an action marked with [Authorize] gets called. From there you can either add your own auth logic or call through to the base methods, and then redirect to the appropriate error or form if the extra data needs filling in. You should be able to tack on their original request as a return URL query parameter so that the user can continue to wherever they were going once the extra data is taken care of. You'll then need to replace all uses of [Authorize] with this custom attribute, but find and replace should take care of that.
Related
I have to implement HttpModule for a condition which should return http status 401 if condition get failed before request hits the controller. In this condition i need to access database to compare some values, My question is, Is it a good practice to use dbcontext inside the HttpModule implementation? or there are any other ways to achieve the same.
NOTE: I know the same can be done through the Custom Authorize attribute, but for that i need to change in lot of places.
Any help will be appreciated.
Usually we have a base controller in all our applications and that will be handling all the filtering and condition checking based on the request url, role and some more conditions, if all meets only the url redirection will perform and the request will hit the actual controller.
My suggestion is to have some kind of mechanism to keep base controller or some OOP approach in all your controllers, that will be much easier when you want to modify something which are common behavior
I have this situation where the fact that the user is not logged in is preventing the construction of my controller's dependencies.
[Authorize]
class MyController : Controller
{
public MyController(MyService service)
{
}
}
class MyService
{
public MyService()
{
// requires information which only
// becomes known after the user logs in
}
}
My question is: can I do something to cause the MVC framework to first look at the Authorize attribute and then resolve the controller instance?
The above would be much more preferable to me than either of the following:
Changing MyService to be able to handle being created before user log in
Injecting Func
Switching to service location
Ideally, I'd like to flip a switch in the MVC framework that says, "before you resolve the controller, check that you're actually going to use it and not toss it out due to lack of authorization and direct anyway..."
I have this situation where the fact that the user is not logged in is preventing the construction of my controller's dependencies.
That's the root of your problem.
// requires information which only becomes known after the user logs in
This means that the constructor of that service does too much. Constructors should not do more than store the incoming dependencies. This way you can compose object graphs with confidence.
The building of object graphs should in general be static. This means that the resolved object graph should not change based on runtime conditions (there are exceptions, but this is a good rule of thumb). It shouldn't matter whether or not a user is authorized or not, the service class should still be composed and injected. This means that authorization and loading of data is done at a later point in time; the moment that the request is actually executed (which is directly after the object graph is composed).
Your problem is that you don't really understand how the MVC Request pipeline works.
The first thing you have to realize is that Attributes are, in essence, designed to match up with identical events in the controller base class. There is an OnAuthorization method in Controller, and this is called either just before or just after the attributes OnAuthorization method is called.
So, in order for it to call both methods at roughly the same time, that means the Controller class must have been constructed to do so. What's more, a lot of other stuff goes on before Authorization filters, such as model binding, because your authorization filter may need information from the model to make its decision.
I suggest you check out this pipline chart.
https://www.simple-talk.com/dotnet/.net-framework/an-introduction-to-asp.net-mvc-extensibility/
I have an authorize attribute that extends System.Web.Http.AuthorizeAttribute and overrides the onAuthorization method. It queries the DB with a token that comes from the request to see if the session is valid. From that, it knows the associated userId. I would like to somehow make the userId available to the controller of the action being called. Somehow setting an instance variable would be ideal because I want to unit test the controller. Perhaps that is not possible or there is a better way to go about doing it. Please let me know. I am using ApiController.
Thanks
Not sure if this is the appropriate way to handle this situation, but to answer my question, one can use actionContext.ControllerContext.Controller. From there I can call a setter or set a public instance variable Please let me know if this a bad approach. Regarding sessions with REST, I am not too concerned with having a pure REST implementation.
As I've found here, I can change the webconfig to allow/disallow methods on webservices.
I need only one method to be a GET and for the others it should be a POST, is there a way to configure just one method (or maybe webservice if there is no other way) to accept GET requests? I am on IIS7.
You can do it by changing the handler mappings, either in IIS or through the httpHandler mappings defined in the web.config.
Or you can have an HttpModule do it.
However, since you are already using asp.net (to judge from your tags) and you've only one exception, then an easier way is probably just to do it at that level. If not, the logic is much the same for doing this from an HttpModule.
In your page-base class (if you don't already define an abstract class in between System.Web.UI.Control.Page and your own pages it might be worth looking at, it's a handy place to put commonly used methods) put a virtual member that gets called before the main page-load handler (e.g have a method called OnLoad that calls this and then your "real" page-load method).
In this method, check the http method used, and if it's not correct set the status code to 405, output an error page for bonus marks, and then stop all processing.
In your page that allows get, override and change the method you check for.
If your class structure doesn't allow this to be done easily, then the HttpModule approach will be easier. Here you'll have to examine the URI to know which method to allow, but the rest is pretty much the same.
Depends on the web server.
You can return errors on certain requests in Apache, for instance.
Use the Limit directive:
<Directory />
Options All
AllowOverride All
<Limit POST PUT DELETE CONNECT PROPFIND PROPPATCH>
# Require valid-user
Deny from all
</Limit>
</Directory>
Edit - Just found the documentation on this: http://httpd.apache.org/docs/2.0/mod/core.html#limit
I've got some things I do in the OnActionExecuting method in a BaseController, that all my other controllers are based off of.
I'm doing some simple things like putting a variable into ViewData that "nearly" all of my views will need, and populating a couple properties that my controllers use.
Thing that bugs me is, this work is being done even on actions that don't need it. Is there a better place to hook into to more efficiently perform this work? In case I ever need to something a little "heavier" than what I do now (i.e. DB access, etc...).
UPDATE: I'm more specifically referring to a typical controller scenario. Where there are several actions that simply show a view. And a few that take a form submission, do some work, and redirect to another action.
In this case, I want the actions that show views to use the work that is done in the OnActionExecuting method. But the actions that accept form submissions, the work being done in OnActionExecuting is not being used and therefor just adds unnecessary processing time.
Maybe I'm not explaining it very well... hope it's clearer now.
TIA!
If it's easier to blacklist actions (by attributing actions for which this logic shouldn't be performed) than whitelisting actions, you could create a [SuppressWhateverLogic] attribute and apply it to the methods you want to be blacklisted. Then modify your OnActionExecuting() method to look for this attribute (via ActionExecutingContext.ActionDescriptor.IsDefined()), and if the attribute exists then bail out of the logic.
If it's easier to whitelist actions, move the logic out of Controller.OnActionExecuting() and create a custom [MyLogic] filter by subclassing ActionFilterAttribute. Add the logic to MyLogicAttribute.OnActionExecuting(), then attribute the methods you want with [MyLogic] to associate the logic with those methods.
Create a second "AdvancedBaseController" which derives from BaseController?