views:

3811

answers:

5

About 6 months ago I rolled out a site where every request needed to be over https. The only way at the time I could find to ensure that every request to a page was over https was to check it in the page load event. If the request was not over http I would response.redirect("https://mysite.com")

Is there a better way -- ideally some setting in the web.config?

+19  A: 

found this

http://www.netnewsgroups.net/group/microsoft.public.dotnet.framework.aspnet/topic34203.aspx

basically

protected void Application_BeginRequest(Object sender, EventArgs e)
{
   if (HttpContext.Current.Request.IsSecureConnection.Equals(false))
   {
    Response.Redirect("https://" + Request.ServerVariables["HTTP_HOST"]
+   HttpContext.Current.Request.RawUrl);
   }
}

that would go in the global.asax.cs (or global.asax.vb)

i dont know of a way to specify it in the web.config

John Boker
+1: I just used implemented this, it works great!
Brian MacKay
+6  A: 

If you are unable to set this up in IIS for whatever reason, I'd make an HTTP module that does the redirect for you:

using System;
using System.Web;

namespace HttpsOnly
{
    /// <summary>
    /// Redirects the Request to HTTPS if it comes in on an insecure channel.
    /// </summary>
    public class HttpsOnlyModule : IHttpModule
    {
        public void Init(HttpApplication app)
        {
            // Note we cannot trust IsSecureConnection when 
            // in a webfarm, because usually only the load balancer 
            // will come in on a secure port the request will be then 
            // internally redirected to local machine on a specified port.

            // Move this to a config file, if your behind a farm, 
            // set this to the local port used internally.
            int specialPort = 443;

            if (!app.Context.Request.IsSecureConnection 
               || app.Context.Request.Url.Port != specialPort)
            {
               app.Context.Response.Redirect("https://" 
                  + app.Context.Request.ServerVariables["HTTP_HOST"] 
                  + app.Context.Request.RawUrl);    
            }
        }

        public void Dispose()
        {
            // Needed for IHttpModule
        }
    }
}

Then just compile it to a DLL, add it as a reference to your project and place this in web.config:

 <httpModules>
      <add name="HttpsOnlyModule" type="HttpsOnly.HttpsOnlyModule, HttpsOnly" />
 </httpModules>
FlySwat
This seems more involved than just sticking it in the global.asax -- just curious, is there an advantage?
Brian MacKay
The advantage would be, when you don't want to use it, just comment out the module in your web.config. This solution *is* configurable, whereas the other is not.
Bob Yexley
I am little confused. I'd expected something like `app.BeginRequest += new OnBeginRequest;` in the `Init` method and in the `OnBeginRequest` would contains what current `Init` method contains. Are you sure that this module works as expected?
Jakub Šturc
+1  A: 

The IIS7 module will let you redirect.

    <rewrite>
        <rules>
            <rule name="Redirect HTTP to HTTPS" stopProcessing="true">
                <match url="(.*)"/>
                <conditions>
                    <add input="{HTTPS}" pattern="^OFF$"/>
                </conditions>
                <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther"/>
            </rule>
        </rules>
    </rewrite>
Mark
A: 

Another advantage in doing the http module is, if you only provide it in global.asax.cs, it only checks SSL upon Application_BeginRequest, which means your app is not fully protected; it will only route to SSL version the first try, then the user could cut and paste the none SSL url and bypass it.

Aaron
Hi Aaron, no that isn't the case, as Application_BeginRequest runs on every request, so if the user changes to http in their browser, they will get redirected to https the next time they hit the server
JonoW
A: 

All --

Note that the default code produced when creating a new ASP HTTP Module in Class Library project in Visual Studio .NET 2008 Standard says the following in the comments...

/// /// You will need to configure this module in the web.config file of your /// web and register it with IIS before being able to use it. For more information /// see the following link: http://go.microsoft.com/?linkid=8101007 ///

...so, for me at least, it is not possible to "register it with IIS" given that I have no control over the server.

As such, even though I would prefer using an HTTP Module if and when I can, if I have no control over the IIS settings then I simply need to the technique of putting the code in Global.asax I guess.

If anyone has something to add, then please do so.

Thank you.

-- Mark Kamoski

mkamoski
Hi Mark, I'm having a hard time following how this is an answer to the question. If you meant to reply to one of the answers, you should leave a comment under that answer. Other you will get downvoted. ;)
Brian MacKay
Also: take a look at the top voted answer, it gives you the technique for using global.asax. I'm using it in production with an SSL cert, works great.
Brian MacKay