HttpModule endless redirect - asp.net

I'm using an HttpModule to try and redirect users to the login page if they're not authenticated, but for some reason it's just endlessly redirecting the page without landing anywhere.
Here's the module:
using System;
using System.Web;
using System.Web.Security;
public class AuthenticationModule : IHttpModule
{
public AuthenticationModule()
{
}
public string ModuleName
{
get
{
return "AuthenticationModule";
}
}
public void Init(HttpApplication app)
{
app.BeginRequest += (new EventHandler(Application_BeginRequest));
}
private void Application_BeginRequest(object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpContext context = app.Context;
HttpRequest request = context.Request;
HttpResponse response = context.Response;
if (!request.IsAuthenticated && !request.RawUrl.Contains(FormsAuthentication.LoginUrl))
{
FormsAuthentication.RedirectToLoginPage();
}
}
public void Dispose() { }
}
I don't recall having ever worked with HttpModules before, so I'm not sure what's not working.
How can I fix this?

request.RawUrl is the URL I entered into the browser. Your check request.RawUrl.Contains(FormsAuthentication.LoginUrl) is case sensitive.
Additionally there are no checks for ressources. So each request for images, css files etc. will redirect to login page. You need to check if authentication is required for the ressource being called.
Edit (hit the save button to early)
Additionally I would do it on AuthenticateRequest

Related

Custom HTTP handler for URL rewriting + session and application variable

Currently my product page URL is like
http://www.localhost:80/products/default.aspx?code=productCode
I want to access product page with
http://www.localhost:80/productCode
I have used HTTP module for this.
public class UrlRewritingModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
context.AuthorizeRequest += new EventHandler(context_AuthorizeRequest);
}
void context_AuthorizeRequest(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
if (some condition)
{
context.RewritePath(url);
}
}
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
//We set back the original url on browser
HttpContext context = ((HttpApplication)sender).Context;
if (context.Items["originalUrl"] != null)
{
context.RewritePath((string)context.Items["originalUrl"]);
}
}
}
I have register it in web.config and it is working fine. But when I deploy it in IIS that session and application variables are not throwing null referent Exceptions.
Can anyone help me?
Edit: Do it require extra code to access session/ Application variable for rewritten URLs
?
Have you tried using HTTPContext.Current?
I was able to solve issue (accessing session and application variables in subsequent pages rewritten by custom handler) by adding runAllManagedModulesForAllRequests="true" attribute in modules in web.config.

Redirect URL Using HttpModule Asp.net

I have created an HttpModule so that Whenever I type "localhost/blabla.html" in the browser, it will redirect me to www.google.com (this is just an example, it's really to redirect requests coming from mobile phones)
My Questions are :
1) How do I tell IIS(7.0) to redirect each request to the "HttpModule" so that it is independent of the website. I can change the web.config but that's it.
2) Do I need to add the .dll to the GAC? If so, How can I do that?
3) The HttpModule code uses 'log4net' . do I need to add 'log4net' to the GAC as well?
Thanks
P.S. the site is using .net 2.0.
You can use request object in BeginRequest event
public class MyHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(this.context_BeginRequest);
}
private void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
//check here context.Request for using request object
if(context.Request.FilePath.Contains("blahblah.html"))
{
context.Response.Redirect("http://www.google.com");
}
}
}

Using HttpModules to modify the response sent to the client

I have two production websites that have similar content. One of these websites needs to be indexed by search engines and the other shouldn't. Is there a way of adding content to the response given to the client using the HttpModule?
In my case, I need the HttpModule to add to the response sent to the when the module is active on that particular web.
You'd probably want to handle the PreRequestHandlerExecute event of the application as it is run just before the IHttpHandler processes the page itself:
public class NoIndexHttpModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += AttachNoIndexMeta;
}
private void AttachNoIndexMeta(object sender, EventArgs e)
{
var page = HttpContext.Current.CurrentHandler as Page;
if (page != null && page.Header != null)
{
page.Header.Controls.Add(new LiteralControl("<meta name=\"robots\" value=\"noindex, follow\" />"));
}
}
}
The other way of doing it, is to create your own Stream implementation and apply it through Response.Filters, but that's certainly trickier.

How to intercept and pre-process QueryStrings in Asp.Net

We send out registration urls to clients via email. Some of the email clients are turning the url into
url <url>
I think it may be happening when users forward the email onto themselves at which point the email client re-formats the original email (maybe)
E.g.
https://my.app.com/login.aspx?param=var
Becomes
https://my.app.com/login.aspx?param=var%20%3Chttps://my.app.com/login.aspx?param=var%3E
Which rightly produces System.Web.HttpRequestValidationException: A potentially dangerous Request.QueryString value was detected
Where in the code should I intercept these instances and santize the url so that the user is re-directed onto the original form of the url?
global.asax?
Page_Init?
HttpHandler?
Pipeline?
You can catch it in Global Application_BeginRequest or in the same event in an HttpModule.
Global
using System;
using System.Web;
namespace MassageIncomingRequestUrl
{
public class Global : HttpApplication
{
protected void Application_BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication) sender;
string path = app.Context.Request.Url.PathAndQuery;
int pos = path.IndexOf("%20%3C");
if (pos > -1)
{
path = path.Substring(0, pos);
app.Context.RewritePath(path);
}
}
}
}
Module
using System;
using System.Web;
namespace MassageIncomingRequestUrl
{
public class UrlMungeModule : IHttpModule
{
#region IHttpModule Members
public void Init(HttpApplication context)
{
context.BeginRequest += BeginRequest;
}
public void Dispose()
{
//nop
}
#endregion
private static void BeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
string path = app.Context.Request.Url.PathAndQuery;
int pos = path.IndexOf("%20%3C");
if (pos>-1)
{
path = path.Substring(0,pos);
app.Context.RewritePath(path);
}
}
}
}
This will get your request processed with the correct query string in the Request, regardless of what you see in the browser address. You may be able to take extra steps to remove the garbage from the reported url but that is mainly just aesthetics.

ASP.NET SSL - issue is the postback, so OnInit etc won't work

When should I enforce SSL for secure pages in an ASP.NET page life-cycle?
I mean should I do it inside page_load? or OnInit? or some other function?
I am using the following code to enforce SSL for certain pages, but where should I put this code? Earlier I placed it inside OnInit function, but that did not work well with ASP.NET wizards. Do I need to check whether it's postback or not first?
If postback drops https, shouldn't my code enforce it? If postback does not drop https, shouldn't my code stop redirecting and move to the next step of the wizard? It seems like it keeps redirecting.
if (!HttpContext.Current.Request.IsSecureConnection) {
HttpContext.Current.Response.Redirect(SiteNavigation.ResolveAbsoluteUrl(true, HttpContext.Current.Request.Url.PathAndQuery));
}
You have basically two options.
If you want all authenticated pages to run under SSL, you can set the requireSSL="true" attribute on forms authentication. Just make sure your login page is also running on HTTPS.
You can also set this on a page-by-page basis. I found this works well in a "page base" class that inherits from System.Web.UI.Page, and that all your pages inherit from (instead of System.Web.UI.Page).
public class PageBase : System.Web.UI.Page
{
public bool RequiresSSL {get; set;}
string currentPage = Request.Url.ToString();
public PageBase()
{
Init += new EventHandler(PageBase_Init);
}
void PageBase_Init(object sender, EventArgs e)
{
if ((RequiresSSL) && (WebConfigurationManager.AppSettings["SSLavailable"] == "true"))
{
if (currentPage.ToLower().StartsWith("http://"))
{
redirectTo = "https://" + currentPage.Substring(7);
Response.Redirect(redirectTo);
}
}
else
{
if (currentPage.ToLower().StartsWith("https://"))
{
redirectTo = "http://" + currentPage.Substring(8);
Response.Redirect(redirectTo);
}
}
}
}
The AppSettings value of SSLavailable allows you to switch the whole mechanism off when you're running in test mode without SSL.
For pages that need to run in SSL mode, all they need to do is set RequiresSSL:
public partial class ChangePassword : PageBase
{
public ChangePassword()
{
PreInit += new EventHandler(ChangePassword_PreInit);
}
void ChangePassword_PreInit(object sender, EventArgs e)
{
RequiresSSL = true;
}
}
It works, very smoothly, and any other pages they go to after the secure page will automatically switch back to HTTP protocol.
I usually do this in the OnPreLoad event to force SSL:
protected override void OnPreLoad(EventArgs e)
{
base.OnPreLoad(e);
String qs;
qs = Request.QueryString;
//// Force the page to be opened under SSL
if (!Request.IsSecureConnection)
{
if (qs != "")
{
qs = "?" + qs;
}
Response.Redirect("https://" +
Request.ServerVariables["SERVER_NAME"].ToString() +
Request.ServerVariables["PATH_INFO"].ToString() + qs);
}
}
If you want to force SSL for all pages, it may be a good fit for an HttpModule. I have come up with the following:
using System;
using System.Web;
namespace CustomHttpModules
{
public class EnforceSSLModule : IHttpModule
{
public void Init(HttpApplication httpApp)
{
httpApp.PreRequestHandlerExecute += this.OnPreRequestHandlerExecute;
}
public void Dispose()
{
}
public void OnPreRequestHandlerExecute(object o, EventArgs e)
{
using (HttpApplication httpApp = (HttpApplication)o)
{
if (HttpContext.Current != null)
{
HttpContext ctx = HttpContext.Current;
String qs;
qs = ctx.Request.QueryString;
//// Force the page to be opened under SSL
if (ctx.Request.IsSecureConnection)
{
if (qs != "")
qs = "?" + qs;
ctx.Response.Redirect("https://" +
ctx.Request.ServerVariables["SERVER_NAME"].ToString() +
ctx.Request.ServerVariables["PATH_INFO"].ToString() + qs);
}
}
}
}
}
}
To use the HttpModule in IIS5.1 or IIS6, drop the compiled assembly for the HttpModule in your site's bin folder and add the following to your web.config's HttpModules section:
<add type="CustomHttpModules.EnforceSSLModule, dllname" name="EnforceSSLModule" />
(where dllname is the name of your assembly file without the extension)

Resources