I'm working on an app using ASP.Net's form authentication. The client also makes RESTfull calls to the server (ExtJS components on front end).
We are using a custom HttpHandler for the service calls.
My problem is that anytime the anytime the authentication cookie expires my HttpHandler 's ProcessRequest method isn't called in order for me to check for the cookie's absence and redirect the user to log in again.
An example would be a user leaves a page open then comes back in 20 mins and clicks on a dropdown that is loaded asynchronously. The app just hangs never getting to my handler.
Any thoughts?
Highly suggest reading the section entitled "The Pipeline Event Model" in this MSDN magazine article: Securely Implement Request Processing, Filtering, and Content Redirection with HTTP Pipelines in ASP.NET.
In a nutshell, authentication is performed well before the request is handed over to ProcessRequest() in your HttpHandler. If you need to handle these cases, you will need to hook into the pipeline events (such as BeginRequest or Authenticate Request) and add your own handlers, like so:
public class EnableWebServicesModule :
IHttpModule
{
public void Init(HttpApplication app)
{
// register event handler
app.BeginRequest += new EventHandler(this.OnBeginRequest);
}
public void OnBeginRequest(object obj, EventArgs ea)
{
// Check if security works here by looking for the cookie or
// the user context.
}
...
}
For further reading on this fascinating and exciting topic, check Rich Strahl's walkthrough: A low-level Look at the ASP.NET Architecture
Related
In my MVC project, there are multiple actions where security between requests and responses is increased with the [ValidateAntiForgeryToken] attribute. This works fine. Problems arise when a user keeps the page open for several minutes (I assume 20, (Session State timeout?)) and then sends a request to the server. This causes an error, because the token sent back no longer matches the token on the server.
Reading this question, it can be solved by adding a HandleError attribute on each specific action that uses [ValidateAntiForgeryToken].
Is there a way to set this globally for the entire website? I'd hate setting it on every action separately.
You can regsiter an ActionFilter globally in global.asax on Application_Start() event.
protected void Application_Start()
{
// Register global filter
GlobalFilters.Filters.Add(new HandleErrorAttribute());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
Who sets the User property of the System.Web.HttpContext object? I am assuming that the classes responsible for authentication, such as one of the methods of the FormsAuthentication class, would be setting this property after successful authentication.
What if I use forms authentication in my application but without using any of the methods of the FormsAuthentication class such as RedirectFromLoginPage but instead use Response.Reirect instead? Will the User property still be set?
The HttpApplication of your web application (inherited by your global.asax) exposes an event AuthenticateRequest which you can subscribe on from within an IHttpModule.
If you take a look at the System.Web.Security.FormsAuthenticationModule then you'll see that it uses the FormsAuthentication class itself to read/write the authentication cookie.
That authentication cookie is added to the list of cookies that will be sent back in response to the web request. It doesn't matter whether the response is a redirect made be a call to RedirectFromLoginPage or a simple Response.Redirect, the cookie will be sent down and each subsequent request will send that same cookie to the server, where it will be processed by the System.Web.Security.FormsAuthenticationModule, which in its turn will set the User if the authentication cookie is available and valid.
You can also subscribe to that same AuthenticateRequest inside your own IHttpModule or directly in your global.asax by specifying the following method for instance:
public class MyApplication : HttpApplication
{
...
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
// assign here some custom `IPrincipal` to the Context.User property
}
...
}
That way you can even set your own IPrincipal implementation if you want.
I am trying to customize a vended product that routes all requests through a HttpHandler. The handler analyzes the request to figure out what page to route the user to and performs a Server.Transfer(). Unfortunately, I need to access SessionState on a page and the handler doesn't implement IRequiresSessionState and is marked as internal so I can't inherit from it. After a lot of googling the best solution I found was to create an HttpModule that changes the handler that processes the request at different points in the request lifecycle. On PostMapRequestHandler I would change the handler that processes the request to my own that implements IRequiresSessionState and PostAcquireRequestState I would map it back.
This works but does anyone have a better solution?
I figured out a more elegant way to enable session state. You can override the session state behavior of a handler. I created a module that forces session state.
public class SessionEnablerModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.PostMapRequestHandler += new EventHandler(context_PostMapRequestHandler);
}
void context_PostMapRequestHandler(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
if ((app.Context.Handler.GetType().ToString().Equals("Handler I want to enable session state for")))
{
//enable session state
app.Context.SetSessionStateBehavior(SessionStateBehavior.Required);
}
}
}
Another solution could be to route all request through your handler that requires session state and then pass those requests to internal handler by invoking its ProcessRequest method - you can create the instance of internal handler by using say Reflection (or using handler factory if any).
However, using HttpModule to swap handlers is definitely a better solution. Because you can choose to swap the handler selectively by looking at the requested URL. That way, you may not have to load/save session state for all requests (that can be expensive operation for out-of-proc sessions)
I'm just reading about implementing my own HTTP handler for ASP.NET 4.0 and IIS7. This looks really cool. I want special processing for ZIP files and it seems like an HTTP handler is the perfect solution.
However, what's giving me trouble is that the handler must be in a separate assembly. So how can I access the rest of my application from this assembly?
Specifically, I'd like to determine if the user is authenticated and redirect them to the login page if they are not. But User.Identity.IsAuthenticated, etc. will not be available from my handler.
(Yes, I know there are ways to approach this without an HTTP handler but they don't seem appropriate for my specific needs.)
User.Identity.IsAuthenticated, etc. will not be available from my handler.
The ProcessRequest method gives you the current HTTP context from which you could determine if the user is authenticated:
public void ProcessRequest(HttpContext context)
{
if (!context.User.Identity.IsAuthenticated)
{
// the user is not authenticated
}
...
}
We have a .net asmx web service that gets called from javascript (using ASP.Net AJAX), and requires access to Session.
[WebMethod(true)]
public string DoSomethingOnTheServer() { }
We're running into the problem of session being locked on a read/write request. Is there any way to mark a web service method as requiring read-only access to Session?
Thanks!
This is a really old thread, but i stumbled on it in my search for an answer to the same question.
I found the answer else where, and will leave it here for other internets in my place:
In Global.asax you can specify for each request, what access the request should have to the session object, and thereby if it should block or not.
private void Application_BeginRequest(object sender, EventArgs e)
{
// This will set the session to read only for asmx services
// This will make the asmx services non blocking for other requests as it doesnt lock the session object
if (Context.Request.Path.Contains(".asmx/"))
{
Context.SetSessionStateBehavior(SessionStateBehavior.ReadOnly);
}
}
This way asmx services always only have read only access to the session and will not block other requests
This http://msdn.microsoft.com/en-us/library/aa480509.aspx page seems to suggest that the answer is "no" - you cannot mark a WebSerivce as having EnableSessionState=ReadOnly.
If you are making simultaneous Web service calls from the same process, the requests will be serialized at the server so that only one will execute at any one time. Unlike .ASPX pages that have support for read-only access to the HttpSessionState object, which allows for simultaneous processing of multiple requests, there is no such capability with ASP.NET Web services. All Web method calls with sessions enabled have read/write access and will be serialized within each session.
Warning: That article is old (2002).
According to the MSDN documentation of the WebMethod Attribute there are several possible properties, so I'm not sure what the 'true' value in your WebMethod Attribute going to do.
Have you tried:
[WebMethod(EnableSession=true)]
According to this document that should give you full access to the session.