In my previous post I talked about a Module-and-Handler to stop referrer spam.
Well, I worked out a smarter version which uses a single HttpModule alernative:
This is the new implementation of the BeginRequest event handler of the Module:
/// <summary>
/// Handles referral requests
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void context_BeginRequest(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
// no action for requests already authorized, without referrer or whose referrer is in the current domain
if (!(context.CurrentHandler is System.Web.UI.Page) || context.Session["_authorized"] != null || context.Request.UrlReferrer == null || context.Request.UrlReferrer.Authority.ToLower() == context.Request.Url.Authority.ToLower())
{
UnsetBadIp();
return;
}
// sets no cacheability
context.Response.Cache.SetNoStore();
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
// refuses requests from BAD IPs
if (isBadIp())
{
TerminateRequest();
}
else
{
// flags the current IP as BAD
SetBadIp();
context.Response.Write("<html><head><script type='text/javascript'>function redirect() { window.location.reload(); }</script><body onmouseover='redirect()'>Redirecting to the requested URL. <a href='javascript:redirect()'>Click here</a> if you are not redirected automatically.</body></html>");
context.Session["_authorized"] = true;
context.Response.StatusCode = 205;
context.Response.End();
}
}
In this version it is the HttpModule itself that issues the client-challanging javascript code.
The first request to any Page is not served: a session variable is set to keep track of the request, and the javascript is issued instead, with a 205 HTTP Status Code (Document Reset... that means further action is required to the client).
If the client sucessfully executes the challange-javascript (a simple page refresh), the HttpModule allows the original handler (Page) to be executed.
Comments are welcome!
Happy coding!