tags:

views:

514

answers:

6

How do I ensure that my users can not physically type in http: to bypass my SSL and ensure that every page is https:?

Possibly a redirect on my master page?

+2  A: 

I would just redirect all http urls to https with a separate page, or use the "require secure channel" option on your IIS configuration, which will display an error if someone tries to access a non-https page.

Here's a site with a guide to redirecting the error page to the https URL of your site.

Alex Fort
+1 for drive-by downvote coward.
Andrew Rollings
Doing this at the web server level is by far the best choice. It provides greater flexibility down the road if you introduce SSL load balancing hardware especially.
Nissan Fan
+8  A: 

This would generally be handled via IIS configuration or with an ISAPI filter, but if you want to do it in the application code, you could put something like this in the Page_Init event of your master page...

If Not Request.IsSecure
    Response.Redirect(Request.Url.AbsoluteUri.Replace("http://", "https://"))
End If
Josh Stodola
Not the best of ideas. You are doing a client side redirect back to the calling page. If there is no SSL for whatever reason (no cert or bad cert) you'd go into a recursive loop. A better choice would be to redirect to an error page as the user shouldn't enter a secure-only site/page unless code incorrectly does so or they are messing with the URL.
Nissan Fan
This works well with the caveat that the string.replace method will change all occurrences of "http://" to "https://", not just the initial scheme. I.e. it may interfere with query string parameters.
Daniel Ballinger
@Daniel if you have the : or / characters in your query strings then you will have other problems to worry about ;)
Josh Stodola
@Nissan I think it is safe to assume that you need a valid certificate in order for this method to work.
Josh Stodola
@Josh I think you're missing my point ... redirecting the user back to a URL in a non-standard scenario shouldn't be done as it can be endlessly recursive and thus confusing.
Nissan Fan
@Josh Agreed, : and / should be escaped when used elsewhere (E.g. querystring parameters). I'm not 100% sure that AbsoluteUri will return the querystring escaped though. Then again, I might be mistaken...
Daniel Ballinger
@Nissan I'm not missing your point at all, I am just deeming it as irrelevant in this particular case. Perhaps you missed the very first sentence of my answer?
Josh Stodola
A: 
if(!String.Equals(Request.Url.Scheme,
                  "https",
                  StringComparison.OrdinalIgnoreCase)) { }
abatishchev
This is a readonly property - see http://msdn.microsoft.com/en-us/library/system.uri.scheme.aspx
Rich
Yes, it is. It's OK for string comparison, isn't i?
abatishchev
Yep, and it looks like your answer has been edited to reflect that. I had only commented because the first post made it appear that you could programatically change the Scheme from http" to "https".
Rich
A: 

If you want to accept only secure connections, create a separate service for port 80 that only redirects to HTTPS. Ideally, you would preserve the requested path in the HTTP redirect.

If you simply want to encourage HTTPS connections for browsing (and don't care about robots, e.g.), add this to your pages:

<script type="text/javascript">
if(location.protocol=='http:')
  location=location.toString().replace(/^http:/,'https:');
</script>
brianary
A: 

I've done this with an HTTPModule so that you don't have to worry about putting the code in every master page (if you have more than one). This version also turns off the redirect for localhost so you don't have to have SSL on your own machine. Basically you make a new HTTP module like this:

Public Class RedirectToHttpsModule
    Implements IHttpModule

    Public Sub Dispose() Implements IHttpModule.Dispose

    End Sub

    Public Sub Init(ByVal context As HttpApplication) Implements IHttpModule.Init
        AddHandler context.BeginRequest, AddressOf context_BeginRequest
    End Sub

    Private Sub context_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        Dim application As HttpApplication = TryCast(sender, HttpApplication)
        If Not application.Request.IsSecureConnection And Not application.Request.IsLocal Then
             application.Response.Redirect(application.Request.Url.ToString().Replace(application.Request.Url.Scheme, "https"))
        End If
    End Sub

End Class

You also have to add the appropriate line in web.config for the HTTPModule:

<httpModules>
      <add type="RedirectToHttpsModule" name="RedirectToHttpsModule" />
</httpModules>
patmortech
+1  A: 

The following builds upon Josh Stodolas answer (IsSecureConnection) but uses the UriBuilder to change the scheme to https rather than a string replace. The benefit of this approach is that it won't change all the occurrences of "http" in the URL to "https".

if (!Request.IsSecureConnection)
{
    UriBuilder newUri = new UriBuilder(Request.Url);
    newUri.Scheme = Uri.UriSchemeHttps;
    Response.Redirect(newUri.Uri.AbsoluteUri);
}
Daniel Ballinger