I'm creating a HTTP module by implementing IHttpModule and I'd like to handle the Authenticate event, raised by the Forms Authentication module.
The documentation only states how to handle this event from within Global.asax, how can I handle this event from within my HTTP module?
You can handle the AuthenticateRequest event of the HttpApplication that is passed to the Init method of your IHttpModule implementation:
// IHttpModule.Init
public void Init(HttpApplication context)
{
// subscribe to the AuthenticateRequest event
context.AuthenticateRequest += this.onApplicationAuthenticateRequest;
}
private void onApplicationAuthenticateRequest(object sender, EventArgs e)
{
// your code goes here
}
This article has an example of the basic authentication in Web API which uses custom HttpModule, might be helpful.
Related
I looked for an answer to this for quite sometime now but didn't find any.
I will refer to Application start as a stage.
Most of the documentations out there talk about the Global.asax file and the Application_Start method which is invoked only once when the first request reaches the Application, even if this behaviour is similar to subscribing to an event it's technicaly not an event.
While lifecycle events such as BeginRequest, AuthenticateRequest and so on are accessible through the application instance as events, the Application.Start is not.
I can subscribe to BeginRequest event in an HttpModule.Init() method or Global.asax Init() method but not to the Application.Start stage like so:
Module
public class MyModule : IHttpModule
{
public void Init(HttpApplication httpApplication)
{
httpApplication.BeginRequest += new EventHandler(ApplicationBeginRequest);
}
}
Global
public class Global : HttpApplication
{
public override void Init()
{
BeginRequest += new EventHandler(ApplicationBeginRequest);
}
}
My question:
Since there is no HttpApplication.Start event accessible from the Application instance, is Global.asax and the "Application_Start" method the only hope to subscribe to the Application start stage ?
After jumping to the .NET source code i found that the HttpApplicationFactory class looks for a method named Application_OnStart or Application_Start in the Global.asax file and then invokes it using reflection => ReflectOnMethodInfoIfItLooksLikeEventHandler().
I don't have the answer why HttpApplication.Start is not event but it's clearly intended to be handled in an event like fashion using Application_OnStart or Application_Start methods.
Ok, so I have quite a task here:
The background of this project is very complex and fully covered by NDA's so I'll just state what I am trying to do without the background.
So what I need is a way to record every request made to an MVC application and every response from it.
Furthermore, I also need a way to "reply" the requests exactly as they were sent.
I was hoping that I could create some solution that "loads" the MVC application, Self hosts or runs in IIS, get requests, records them and passed them verbatim to the MVC application which would then act exactly like any other MVC app.
I could then create a second solution that "loads" the MVC app but instead of opening it up to request it would read the events from the event store and "replays" them in the MVC app.
Now I have no clue where to even start. This kinda thing is way out of my comfort zone.
If there is another solution for how I can record and replay request (and responses) then please let me know.
Even if there is a way to intercept a request in MVC before it starts doing all of its authentication and routing malarkey then that would be a great starting point. I would also need to know where I can capture the response at the very last second before it is sent.
Many thanks for your time
Andy
A HttpModule would work just fine for your scenario:
using System;
using System.Web;
public class HelloWorldModule : IHttpModule
{
public HelloWorldModule()
{
}
public String ModuleName
{
get { return "HelloWorldModule"; }
}
// In the Init function, register for HttpApplication
// events by adding your handlers.
public void Init(HttpApplication application)
{
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.EndRequest +=
(new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source,
EventArgs e)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
/*...*/
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
/*...*/
}
public void Dispose() { }
}
The code and more information available here.
I am trying to create a custom HttpModule which controls which users can view a site.
I am trying to leverage Windows Authentication to do this.
On an individual page, I would probably do something like this:
if (HttpContext.Current.User.Identity.Name.Contains("jsmith"))
{
Response.Write("You do not have the correct permissions to view this site.");
Response.End();
}
But because I want to make this more configurable at the application level, I would like to use an HttpModule.
Here is the start that I have made on the code:
using System;
using System.Web;
public class CustomAuthHttpModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(OnBeginRequest);
context.EndRequest += new EventHandler(OnEndRequest);
}
void OnBeginRequest(object sender, EventArgs e) { }
void OnEndRequest(object sender, EventArgs e)
{
HttpApplication appObject = (HttpApplication)sender;
HttpContext contextObject = appObject.Context;
if (contextObject.User.Identity.Name.Contains("jsmith"))
{
contextObject.Response.Clear();
contextObject.Response.End();
}
}
}
I would be fine with using the code I have, if I could put it in the OnBeginRequest() function. But the User property is not created in the HttpContext object until OnEndRequest() runs.
Running the code earlier would prevent the application from doing the extra work of producing this output, since some users are just going to be blocked from access in the end.
Can someone suggest a solution to this - is this happening because my module is running before the Windows Auth module, or what?
... or, maybe there is an easier way to do what I am trying to do with IIS or file system permissions?
You want the AuthenticateRequest event.
AuthenticateRequest event
Have you tried to implement the method in the global.aspx? OnSessionStart?
Besides I would use hasRole or some other group-Property instead of contains and username.
Why write an http module for this. If this is asp.net web forms then why not simply use built in stuff like LoginView http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.loginview.aspx
I am writing a custom c# HttpModule that will handle requests from all file types. As a simple proof of concept I have setup the module by adding a reference to the httpModules section of the web config and added application extensions for the demo IIS website with a reference to the aspnet_isapi.dll so that it currently only intercepts request for ".htm" files
But even if there is no significant code in the "OnBeginRequest" event (code below) it causes an infinite redirect loop. I am using IIS 5 on XP Anyone got any ideas?
So far I have only seen HttpModule examples for use with ASPX files but surely you can configure the for any file type?
#region IHttpModule Members
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(OnBeginRequest);
}
///
///
///
///
public void OnBeginRequest(Object s, EventArgs e)
{
HttpApplication context = s as HttpApplication;
Uri currentURL = context.Request.Url;
string pageName = currentURL.Segments.Last().ToLower();
}
#endregion
OK. The problem was actually in the HttpModule itself.
It appears that you have to use the HttpApplication context in order for it to render on the client.
For Example after you have performed all your custom logic you need to write to the context:
context.Response.Write("/n/r");
//or
context.Response.Redirect("test.htm");
Everything then renders as you would expect
Q 1. To my understanding FormsAuthenticationModule is subscribed to AuthenticateRequest event, and thus only after this event is fired, is FormsAuthenticationModule called. But the following quotes got me a bit confused:
The AuthenticateRequest event signals that the configured authentication mechanism has authenticated the current request.
Doesn’t the above quote suggest that when AuthenticateRequest event is raised, request (aka user) is already authenticated?
Subscribing to the AuthenticateRequest event ensures that the request will be authenticated before processing the attached module or event handler.
As far as I understand this quote, if we subscribe to AuthenticatedRequest, then our event handler will be called prior to FormsAuthenticationModule? Thus Application_AuthenticateRequest() will be called before FormsAuthenticationModule is called?
Q 2. Book I’m learning from suggests that within Application_AuthenticateRequest() we are able to verify whether user is a member of specific role, and if not, we can add the user automatically:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated && Roles.Enabled)
{
//here we can subscribe user to a role via Roles.AddUserToRole()
}
}
Judging from the above code, Application_AuthenticateRequest() is called after FormsAuthenticationModule has been invoked, but somewhere else same book implies that Application_AuthenticateRequest() is called prior to FormsAuthenticationModule:
Application_AuthenticateRequest is called just before authentication is performed.
This is a jumping-off point for creating your own authentication logic.
What am I missing?
Thanx
It seems that the FormsAuthenticationModule gets handled first. This module is normally earlier than any custom module in the ASP.NET pipeline, so when AuthenticateRequest is fired, FormsAuthenticationModule will get called first, do its job and then your module's event handler will be called.
If you really want to dig deep into this, I suggest trying to debug the ASP.NET code yourself. Here is a post how to set up your VS:
http://weblogs.asp.net/scottgu/archive/2008/01/16/net-framework-library-source-code-now-available.aspx
EDIT: I was able to confirm this behavior by setting up a web project with custom module and event handlers in Global.asax. Take a look at the source code of HttpApplication.InitInternal, the order of initialization is as follows:
initialization of integrated modules: FormsAuthenticationModule hooks up to HttpApplication.AuthenticateRequest event
initialization of custom modules: custom module hooks up to HttpApplication.AuthenticateRequest event
initialization of Global class (global.asax): here we hook up to the AuthenticateRequest event
HttpApplication.InitInternal searches for methods on Global class following the specific name pattern (e.g. Application_AuthenticateRequest), matches them to event and hooks up
After the initialization, when the AuthenticateRequest fires, the event handlers are called in the order they where initialized, so:
FormsAuthenticationModule.AuthenticateRequest event handler
CustomModule.AuthenticateRequest event handler
Global.AuthenticateRequest event handler
Global.Application_AuthenticateRequest method
Unless I missed something, there is no mechanism for stopping the event handlers to fire, so no matter what the result of FormsAuthenticationModule.AuthenticateRequest, the next handlers will still be called. I hope that helps.
If you want access to the User object, I'd suggest you use
protected void Application_Start()
{
PostAuthenticateRequest += Application_PostAuthenticateRequest;
}
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
if(User.Identity.IsAuthenticated)
{
//Do stuff here
}
}