Moving to HTTPS on WordPress

I just recently took CSS-Tricks “HTTPS everywhere”. That is, every URL on this site enforces the HTTPS (SSL) protocol. Non-secure HTTP requests get redirected to HTTPS. Here’s some notes on that journey.

Why do it?

General security. When you enforce HTTPS, you’re guaranteeing no information passed between the server and client can be intercepted and stolen or messed with in any way. That’s great for a site like this that has a login system and accepts credit cards in some places and things like that.

The site as it is intended. I’ve heard of examples like hotel WiFi system and even ISPs that mess with HTTP traffic and do things like insert their own advertising code. Can’t do that over HTTPS.

Prereq. I can’t seem to find any good links on this, but I’m under the assumption that HTTPS is required for some/all of the stuff for SPDY / HTTP/2 – which everyone agrees is awesome and super fast. I want to make sure I’m ready so I can start moving forward on that.

Geek cred. Duh.

1. Get an SSL certificate

Not optional. This is how it works. I’ve done this a bunch of times in my life and it’s never overly comfortable. You just need to follow instructions closely. I’ve bought them in the past from discount providers and actually had it work fine, but it’s a more manual process.

When the SSL certificate is installed properly, you should be able to visit your site (any URL) at eitherHTTP or HTTPS and have it come up fine. There may be errors on HTTPS though, and we’ll get to that.

2. Start with the Admin

In WordPress-land, you might as well get HTTPS going in the admin area first. It’s set up to handle itand there probably won’t be any errors. (I keep saying “errors”, I mostly mean “mixed content warnings” which I promise we’ll get to.)

To force HTTPS in the admin area, put this line in your wp-config.php file at the root of your WordPress install:

1

define('FORCE_SSL_ADMIN',true);

Make sure you test that HTTPS is working properly first! Go to https://yoursite.com/wp-admin/ to check. Otherwise you’ll be forcing URLs that don’t work and that’s bad. If you have trouble, remove that line right away.

All goes well, you’ll get a secure connection:

3. Try to get one page working on the front end

The next step is to get your front end on HTTPS. Forcing it all right away is probably going to be tough, so just start with one target page. For me, it was the signup page for The Lodge. That page can take credit cards, so really, it had to be HTTPS. This was the motivator for me early on to get this set up.

There is a plugin that can help with this: WordPress HTTPS (SSL). With that plugin, you get a checkbox on Posts/Pages to force it to be SSL.

4. Mop up Mixed Content Warnings

What you’re really trying to avoid is this:

Mixed Content Warning

That’s like: “Hey nice trying being HTTPS but you aren’t fully so NO GREEN LOCK FOR YOU!”

If you open the console, you’ll likely get messaging like this:

In this case, it was some images being used in a CodePen embed with an HTTP src.

But it could be anything. HTTP <script>s, HTTP CSS <link>s, HTTP <iframe>s. Anything that ends up making an HTTP request that isn’t HTTPS will trigger the error.

You just need to fix them. All.

5. Protocol Relative URLs! (or just relative URLs)

You know, those ones that start with //, like this:

1

<img src="//example.com/image.jpg"alt="image">

Those are your friend. They will load that resource with whatever protocol the current page is. And links that are just relative to begin with will be fine, like:

1

<img src="/images/image.jpg"alt="image">

I ended up finding them all over the place. I even had Custom Fields to fix:

6. Harder problem: images within legacy content

There are thousands and thousands of pages on this site, and lots and lots of images within those pages. Right in the content itself. There are a bunch on this very page you’re looking at. The problem is those images had fully qualified HTTP links on them.

I didn’t relish the idea of using some WordPress filter on content to kinda hotswap those URL’s out – I just wanted to fix the issue. I hired Jason Witt to help me with this. The first thing we did was run some SQL on the database to fix the URL’s. Essentially fixing the src of images to be protocol relative.

After backing up the database, and testing it locally, this worked great:

7. Make sure new images are protocol relative

With the legacy content mopped up, we need to make sure new content stays OK. That means fixing the media uploader/inserter thingy so it inserts images with protocol relative URLs. Fortunately I already customize that to insert with <figure> tags, so it was just an adjustment of that. Jason ultimately helped me move a lot of my custom functions.php code into a plugin, so this is a little out of context, but I think you’ll get the picture and see the relevant filters and stuff:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

classCTF_Insert_Figure{

publicfunction__construct(){

add_filter('image_send_to_editor',array($this,'insert_figure'),10,9);

}

publicfunctioninsert_figure($html,$id,$caption,$title,$align,$url){

// remove protocol

$url=str_replace(array('http://','https://'),'//',$url);

$html5="<figure id='post-$id' class='align-$align media-$id'>";

$html5.="<img src='$url' alt='$title' />";

if($caption){

$html5.="<figcaption>$caption</figcaption>";

}

$html5.="</figure>";

return$html5;

}

}

8. Your CDN needs SSL too

If you have a CDN set up (I use MaxCDN through W3 Total Cache) that means the CDN is totally different server and URL and all that and it needs to be able to serve over HTTPS as well. Fortunately MaxCDN handles it.

9. Start forcing HTTPS everywhere

This is what I do in the .htaccess file at the root:

1

2

3

4

# Force HTTPS

RewriteEngineOn

RewriteCond%{HTTPS}off

RewriteRule(.*)https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Once that is in place, you can turn off the plugin and remove the bit from the wp-config.php file, as those are redundant now.

You’ll also want to change the URL settings in General Settings to be https:// – so all the links in WordPress are constructed properly and redirects don’t need to come into play:

10. Keep mopping up

Inevitably after going HTTPS everywhere, you’ll find pages with mixed content warnings. You just need to keep investigating and fixing.