如果连接是纯HTTP,则尝试了解用于重定向到HTTPS的不同方法

问题描述:

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.

  1. Rewrite rule
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
  1. Redirect rule
<VirtualHost *:80>
    ServerName www.example.com
    Redirect "/" "https://www.example.com/"
</VirtualHost >

<VirtualHost *:443>
    ServerName www.example.com
    # ... SSL configuration goes here
</VirtualHost >
  1. Redirect PHP
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?

所以我在互联网上看到了几种不同的方法,但我不确定它们之间的实际区别是什么 他们或为什么一个比另一个好。 p>

  1. 重写规则 li> ol>
      RewriteEngine On 
    RewriteCond%{HTTPS}!on 
    RewriteRule(。*)https://%{HTTP_HOST}%{REQUEST_URI} 
      code>  pre> 
     
     
    1. 重定向规则 li> ol>
       &lt; VirtualHost *:80&gt; 
       ServerName www.example.com 
       重定向“/”“https://www.example.com/"
      </VirtualHost&gt; 
       
      &lt; VirtualHost *:443&gt; 
       ServerName www.example.com 
      #... SSL配置进行 这里
      &lt; / VirtualHost&gt; 
        code>  pre> 
       
       
      1. 重定向PHP li> ol> \ n
          if($ _ SERVER ['HTTPS']!=“on”){
         $ redirect =“https://”。$ _ SERVER [“HTTP_HOST”]。$ _ SERVER [  “REQUEST_URI”]; 
        标题(“位置:$ redirect”);  
         exit(); 
        } 
          code>  pre> 
         
         

        目前我正在使用#3,我把它放在一个单独的文件中并将其包含在任何需要HTTPS的页面中 。 p>

        这是不好的做法吗? 我应该使用其他方法来使用HTTPS吗? p> div>

Shorter answer.

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"

Longer answer.

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.

  1. 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.

  2. 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.

  3. 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:

  1. Apache 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.
  2. Apache 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.
  3. PHP code logic. Least efficient since PHP needs to be parsed for the logic to be executed. And since it happens after the other Apache stuff happens, slight edge-risk of a security vulnerability. But the benefit is you can be a plain/non-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.

Bonus: How to debug stuff like this from the command line.

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

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.

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]