George Durzi

in

Update to SharePoint SSL Switching HttpModule

I recently wrote about a Combined SSL HttpModule for SharePoint Webs and Pages that we used on a project to switch a SharePoint site in and out of SSL for certain _layouts pages as well as specific webs within the site collection.

Turns out there was a flaw in the HttpModule that appeared when I was using newer builds of FireFox and IE8. With the HttpModule enabled, I would get browser warnings that my entire connection wasn't encrypted.

FireFox handled this somewhat gracefully, putting a red exclamation mark over the padlock icon. IE8, on the other hand prompted the user if they would like to load the page without the items in question, causing the page to barf <-- technical term.

After spending a lot of time analyzing the traffic with Fiddler (a must in every developer's toolkit), as well as a very helpful suggestion on StackOverflow, I figured out the cause of the issue.

When analyzing the traffic in Fiddler, you could see that the request started as SSL, but was followed by a 301 response, redirecting it to a non-HTTPS link to the resource I was retrieving.

This was happening for items I had in my master page (using relative links!), e.g. my CSS, JavaScript, and general images for look and feel. Interestingly, IE6, IE7, and Chrome ignored the error and showed my site as incorrectly running full SSL. Odd given that I now understood that some resources were in fact not being transmitted over SSL.

Obviously the HttpModule will fire even for requests for "non-HTML" content. Knowing this, I modified the HttpModule to ignore that type of content.

Check out the original post for most of the background code, here's the updated PreRequest handler:

HttpContext ctx = HttpContext.Current;
SPContext spContext = SPContext.Current;

if (spContext != null)
{
    if (spContext.Web != null)
    {
        // Assume that request does not require SSL
        bool requestRequiresSSL = false;
        // Check if the current request is for page content
        //  not gif, js, css, etc.
        bool isHTMLContent = !_ignoreExt.Contains(
            Path.GetExtension(ctx.Request.PhysicalPath).ToLower());
        // Get the request Path and QueryString value
        string pathAndQuery = ctx.Request.Url.PathAndQuery;

        if (isHTMLContent)
        {
            // Layouts pages need to be handled separately
            //
            if (pathAndQuery.ToLower().Contains("_layouts"))
            {
                // Check if the current layouts page requires SSL
                foreach (var page in _sslPages)
                {
                    if (pathAndQuery.ToLower().Contains(page.ToLower()))
                    {
                        requestRequiresSSL = true;
                        break;
                    }
                }
            }
            else
            {
                // Check if the current site requires SSL
                if (spContext.Web.Properties.ContainsKey
                    (SITE_REQUIRES_SSL_PROPERTY))
                    requestRequiresSSL = (spContext.Web.Properties
                        [SITE_REQUIRES_SSL_PROPERTY].ToString()).ToLower()
                        == Boolean.TrueString.ToLower();
                else
                    return;
            }
        }

        if (isHTMLContent)
        {
            // SSL required and current connection is not SSL
            if (requestRequiresSSL && !ctx.Request.IsSecureConnection)
                ctx.Response.Redirect(_baseURLWithSSL + pathAndQuery);

            // SSL not required but current connection is SSL
            if (!requestRequiresSSL && ctx.Request.IsSecureConnection)
                ctx.Response.Redirect(_baseURLNoSSL + pathAndQuery);
        }

Comments

Ulises said:

It would be cool if you could post the whole thing.

# March 30, 2009 6:48 PM

Ulises said:

what extensions should we include in _ignoreExt?

thanks !

# March 31, 2009 11:25 AM

gdurzi said:

Ulises,

I have my _ignoreExt set to contain: ".css", ".js", ".axd", ".gif", ".jpg", ".png"

However, yours should include any other asset types, e.g. swf, that you would like to ignore

# March 31, 2009 11:38 AM

Ulises said:

I don't have SherePoint designer, is there another way to set requiressl?

can I do it in the web.config file?

THANKS !

# March 31, 2009 12:30 PM

Ulises said:

Hey I really appreciate your help, I've been reading other articles and I really think these is what I need. However I've installed it, I hit the page using http and it does not change it to https so I'm trying to figure out what I missed.

That's the reason I was asking for the whole sample of code.

THANKS again !

# March 31, 2009 12:32 PM

gdurzi said:

Hi Ulises,

The reason I didn't post the whole thing is that it is dependent on a bunch of other code that's dispersed across our solution. Some of that was work for a client project, so I couldn't package and post it all. Sorry for the inconvenience.

A couple of things you asked about:

- RequireSSL

I set that as part of our site provisioning process in our site definition. However, you can do it in the object model when you have a reference to your SPWeb object:

myWeb.Properties.Add("RequireSSL", Boolean.TrueString.ToLower());

myWeb.Properties.Update();

- Installing the Module

Remember that you have to have to the HTTPModule listed in your web.config in order for it to work. Check out an existing SharePoint web.config, and it will be obvious where to insert your new module in the list.

The clean way to do it is to use SPWebConfigModification to write out that entry to the httpModules section of your web.config when the feature is activated

# March 31, 2009 2:13 PM

Ulises said:

I finally got it to work, the problem was very simple, I didn't add the SSLLayoutsPages entry to the appSettings since I'm not really sure if I needed it. And the code checks whether it's null, and if it is "return" is called and the following line is not executed:

application.PreRequestHandlerExecute += new EventHandler(PreRequest);

One thing that I found was that IE was alerting me every time I was clicking a link:

The current web page is trying to open a site in your Trusted sites list. Do you want to allow this?

windowsxp.mvps.org/.../zoneelev.htm

windowsxp.mvps.org/.../elevdialog.JPG

I realized this happen since all the links pointed to http instead of https. So I "extended the application" by adding another site that works with SSL and disabling SSL in the original application.

Configuring SSL in SharePoint 2007 development environment

mastykarz.nl/.../SharePointSSL_WebApp.png

After doing this the dialog boxes stopped showing since there were not zone elevations anymore.

The only thing that is bothering me now is that I'm using windows authentication and whenever the user hits the http site it prompts for credentials and once they have been validated the httpmodule redirects them to the https site which prompts for credentials one more time GRRRRRRR.

anyway. Thanks for sharing. Great stuff

Thanks again !

Ulises

ureyes at gmail D0t com

# March 31, 2009 3:10 PM