Reputation: 2467
So I’ve seen a couple different methods on the internet but I’m not sure what the actual difference is between them or why one is better than the other.
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
<VirtualHost *:80>
ServerName www.example.com
Redirect "/" "https://www.example.com/"
</VirtualHost >
<VirtualHost *:443>
ServerName www.example.com
# ... SSL configuration goes here
</VirtualHost >
if($_SERVER['HTTPS'] != "on") {
$redirect = "https://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];
header("Location:$redirect");
exit();
}
Currently I’m using #3, I put it in a seperate file and include it in any page that requires HTTPS.
Is this bad practice? Should I be using a different method to use HTTPS?
Upvotes: 3
Views: 125
Reputation: 26014
In general, this all falls under the “depends” rubric.
But for the example you are showing, I would say simply placing Redirect "/" "https://www.example.com/"
in an .htaccess
file on the plain-HTTP site is the best method. Just note that if you are dealing with specific pages—and I have no clue what your site layout looks like—then the entries in that .htaccess
file might look something like this:
Redirect "/login.php" "https://www.example.com/login.php"
Redirect "/account.php" "https://www.example.com/account.php"
Redirect "/starwars_spoilers.php" "https://www.example.com/starwars_spoilers.php"
You ask this:
So I’ve seen a couple different methods on the internet but I’m not sure what the actual difference is between them or why one is better than the other.
In my humble opinion, I see all of these methods as valid but each has it’s own quirks and idiosyncrasies based on usage and system needs. Based on what you are describing I would recommend using either method number 1 or 2 in an .htaccess
file and just placing it in the server codebase that requires forcing HTTPS connections. But I would only use the PHP method if you have larger coding needs past simple “Is it HTTPS or not?” logic.
Here is my breakdown.
Rewrite rule: The Apache server mod_rewrite
method.
A robust server level method. Your PHP code does not get run before this method happens. This uses the Apache mod_rewrite
module allow commands like RewriteCond
and RewriteRule
to be used. Also, the nice thing about this method is it can be used directly in an .htaccess
document at the root of a website to influence all child content in any directory on that site. Or it can be used in a separate directory. The nice thing here since the logic presented is simple if the connection is not HTTPS (RewriteCond %{HTTPS} !on
) then just redirect traffic to the HTTPS equivalent (RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
) you can just use this in a common code directory that feeds HTTP and HTTPS and let it do the “worrying.”
That said, this stuff is utterly not just usable in an .htaccess
file but can be used in a server level Apache configuration file. The main difference being that while an .htaccess
file can be edited on the fly by any user with read/write access and changes come immediately, if it’s used in an Apache configuration file the user needs to typically have root
/sudo
access to not only edit the files but also restart the Apache web service to get the rules mod_rewrite
rules loaded.
In general, for a set of RewriteRule
commands like this I would actually prefer to place them directly in the server Apache config file—in this case the port 80, plain HTTP configuration block/area—because a config like this is so deep and broad I truly think you would need to only set it once. The negative aspect of this approach compared to the .htaccess
method is over time you might also forget you did this. So if you migrate code to a new server and suddenly HTTP connections work, you might panic a bit… And only later on realize you did this. Which is why—in this simple example—I believe the code logic presented is better served by being in an .htaccess
file that can be placed in a commonly accessed content directory.
Redirect rule: The Apache server mod_alias
method.
A basic server level method which might fit your “per page” needs better. Your PHP code does not get run before this method happens. This uses the Apache mod_rewrite
module allow commands like Alias
and Redirect
to be used. The best way to see this method is that mod_alias
’s first job is to allow you to create aliases that can map a web URL path to a filesystem path. That to me is a very cool ability, but it’s not really applicable towards the issue you describe here which is redirecting plain-HTTP requests to a secure. It’s secondary function is to create a web-URL alias it calls a Redirect
, which is simple way to redirect traffic.
For your simple requirement, the Redirect
command can be used for fairly “lunk-headed” redirect tasks and is useful there. But for anything that requires anything slightly more finessed, it’s not useful. Which might be useful to you?
In the example you posted, you are showing the <VirtualHost *:80>
configuration block which would be a part of a larger Apache server-side configuration that would require root
/sudo
access to set. But honestly the core Redirect "/" "https://www.example.com/"
is all you need and you can just place that in an .htaccess
file on the plain-HTTP site as well if you wish. Depending on the complexity of your site’s code and your own personal comfort, having this Redirect
in an .htaccess
file might be the best “set it and forget it” solution. One line, clean, readable and understandable.
Redirect PHP: The code-based method.
Now this technically works, but you should only really use stuff like this if you have deeper coding logic and needs. Meaning—for example—you have a website whose public front-facing presence really doesn’t need HTTPS and would prefer to leave it at HTTP—since HTTP requires less system overhead than HTTPS—and only redirect to an HTTPS connection after some code logic triggers. Like an administrator login or something like that.
The negative aspect to this method is unless you have a centralized PHP controller file then this becomes a pain in the butt to maintain. Also, if the redirect happens in PHP and not on a server level, that means that technically any connection to the server will need to parse the PHP logic before knowing what to do. This adds a slight overhead to your codebase since PHP needs to be parsed and might open up a potential code vulnerability that could effectively disable the HTTPS code. Meaning, when websites get hacked that really does not happen on the Apache web server level but rather the coding level where stuff like PHP happens. If HTTPS and security is important to you, relying on PHP code alone to handle redirection decision making and connection enforcement might be a bad idea.
And one small final note, here is a breakdown of which placement method os more/less resource intensive and user versus admin level access:
mod_rewrite
or mod_alias
commands directly in the Apache config file. Least resource intensive, but requires root
/sudo
level access to config and access.mod_rewrite
or mod_alias
commands in an .htaccess
file. Slightly more resource intensive on the server since Apache has to parse the .htaccess
file on each request, but honestly unless your server is incredibly high in traffic or disturbingly resource starved, you won’t notice a speed difference with an .htaccess
file. And is nice since you can be a plain/non-root
user with read/write access to adjust.root
user with read/write access to adjust logic if needed. And you can do more complex things with your PHP logic based on your code needs without having to learn what is essentially another language if you attempted the same logic with mod_rewrite
.When dealing with redirects and stuff like this, reloading a web browser can be a pain and inaccurate. When you load a webpage for testing like this the full content—including assets—needs to be downloaded and cached by the browser. Not only that, cached content needs to be cleared for a test to work. Really resource intensive for this kind of debugging. Instead, I recommend using a curl -I
command from the command line to debug returned headers which I find to be an easier and cleaner way to debug things like this.
First set the commands in your .htaccess
file like this:
Redirect "/" "https://www.example.com/"
Save it on the server and then run a curl -I
command like this:
curl -I http://www.example.com/
The returned output should be something like this:
HTTP/1.1 302 Found
Date: Tue, 22 Dec 2015 01:43:32 GMT
Server: Apache/2.2.23 (Unix) mod_ssl/2.2.23 OpenSSL/0.9.8zg DAV/2 PHP/5.4.10
Location: https://www.example.com/
Content-Type: text/html; charset=iso-8859-1
Note the first HTTP
header at the top and the Location:
value near the bottom. The 302 Found
means the redirect is temporary an the Location: https://www.example.com/
tells the browser where to redirect to.
That said, in a case like this you might want to change that Redirect
in .htaccess
to set the header to a 301 Moved Permanently
header which is better for SEO and honestly is describing what you are doing; all HTTP traffic is being permanently redirected to HTTPS. You would do that by charing this:
Redirect "/" "https://www.example.com/"
To this:
Redirect 301 "/" "https://www.example.com/"
Simply adding that 301
after the Redirect
is all you need to do. And after that is done, check the headers again with curl -I http://www.example.com/
and the output should now be:
HTTP/1.1 301 Moved Permanently
Date: Tue, 22 Dec 2015 01:54:51 GMT
Server: Apache/2.2.23 (Unix) mod_ssl/2.2.23 OpenSSL/0.9.8zg DAV/2 PHP/5.4.10
Location: https://www.example.com/
Content-Type: text/html; charset=iso-8859-1
Upvotes: 2
Reputation: 852
The first is used within a .htaccess
file with an Apache web server. You can change this file and do not have to restart your server for changes to take effect. It is executed after your 2nd solution would take place.
The second is similar to this, but stored in a config file of an Apache webserver. If you use this method, you have to restart the Apache web server. This means that your website will be down for a few seconds. But it is possibly the fastest solution in question of processing, it’s the first level to be executed.
The third one works too but takes some milliseconds longer to be executed. Google probably would like you to use the first or second solution, because its Google bot visits your page, too and likes to be redirected earlier than later.
Upvotes: 0
Reputation: 27
You try something like this in your .htaccess file. It will force the site to use HTTPS instead of HTTP.
## FORCE SSL
RewriteCond %{SERVER_PORT} !443
RewriteRule ^(.*)$ https://YOURURL/$1 [R=301,L]
Upvotes: -1