How can I force users to access my page over HTTPS instead of HTTP?

PhpApacheSslHttps

Php Problem Overview


I've got just one page that I want to force to be accessed as an HTTPS page (PHP on Apache). How do I do this without making the whole directory require HTTPS? Or, if you submit a form to an HTTPS page from an HTTP page, does it send it by HTTPS instead of HTTP?

Here is my example:

http://www.example.com/some-page.php

I want it to only be accessed through:

https://www.example.com/some-page.php

Sure, I can put all of the links to this page pointed at the HTTPS version, but that doesn't stop some fool from accessing it through HTTP on purpose...

One thing I thought was putting a redirect in the header of the PHP file to check to be sure that they are accessing the HTTPS version:

if($_SERVER["SCRIPT_URI"] == "http://www.example.com/some-page.php"){
  header('Location: https://www.example.com/some-page.php');
}

But that can't be the right way, can it?

Php Solutions


Solution 1 - Php

The way I've done it before is basically like what you wrote, but doesn't have any hardcoded values:

if($_SERVER["HTTPS"] != "on")
{
header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
exit();
}

Solution 2 - Php

You could do it with a directive and mod_rewrite on Apache:

<Location /buyCrap.php>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</Location>

You could make the Location smarter over time using regular expressions if you want.

Solution 3 - Php

You should force the client to request HTTPS always with HTTP Strict Transport Security (HSTS) headers:

// Use HTTP Strict Transport Security to force client to use secure connections only
$use_sts = true;
 
// iis sets HTTPS to 'off' for non-SSL requests
if ($use_sts && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
    header('Strict-Transport-Security: max-age=31536000');
} elseif ($use_sts) {
    header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
    // we are in cleartext at the moment, prevent further execution and output
    die();
}

Please note that HSTS is supported in most modern browsers, but not universal. Thus the logic above manually redirects the user regardless of support if they end up on HTTP, and then sets the HSTS header so that further client requests should be redirected by the browser if possible.

Solution 4 - Php

I just created a .htaccess file and added :

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

Simple !

Solution 5 - Php

The PHP way:

$is_https=false;
if (isset($_SERVER['HTTPS'])) $is_https=$_SERVER['HTTPS'];
if ($is_https !== "on")
{
    header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
    exit(1);
}

The Apache mod_rewrite way:

RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Solution 6 - Php

// Force HTTPS for security
if($_SERVER["HTTPS"] != "on") {
    $pageURL = "Location: https://";
    if ($_SERVER["SERVER_PORT"] != "80") {
        $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
    } else {
        $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
    }
    header($pageURL);
}

Solution 7 - Php

Had to do something like this when running behind a load balancer. Hat tip https://stackoverflow.com/a/16076965/766172

function isSecure() {
    return (
        (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
     || $_SERVER['SERVER_PORT'] == 443
     || (
            (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
         || (!empty($_SERVER['HTTP_X_FORWARDED_SSL'])   && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on')
        )
    );
}

function requireHTTPS() {
    if (!isSecure()) {
        header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], TRUE, 301);
        exit;
    }
}

Solution 8 - Php

http://www.besthostratings.com/articles/force-ssl-htaccess.html

Sometimes you may need to make sure that the user is browsing your site over securte connection. An easy to way to always redirect the user to secure connection (https://) can be accomplished with a .htaccess file containing the following lines:

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]

Please, note that the .htaccess should be located in the web site main folder.

In case you wish to force HTTPS for a particular folder you can use:

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteCond %{REQUEST_URI} somefolder 
RewriteRule ^(.*)$ https://www.domain.com/somefolder/$1 [R,L]

The .htaccess file should be placed in the folder where you need to force HTTPS.

Solution 9 - Php

Ok.. Now there is tons of stuff on this now but no one really completes the "Secure" question. For me it is rediculous to use something that is insecure.

Unless you use it as bait.

$_SERVER propagation can be changed at the will of someone who knows how.

Also as Sazzad Tushar Khan and the thebigjc stated you can also use httaccess to do this and there are a lot of answers here containing it.

Just add:

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://example.com/$1 [R,L]

to the end of what you have in your .httaccess and thats that.

Still we are not as secure as we possibly can be with these 2 tools.

The rest is simple. If there are missing attributes ie...

if(empty($_SERVER["HTTPS"])){ // SOMETHING IS FISHY
}

if(strstr($_SERVER['HTTP_HOST'],"mywebsite.com") === FALSE){// Something is FISHY
}


Also say you have updated your httaccess file and you check:

if($_SERVER["HTTPS"] !== "on"){// Something is fishy
}

There are a lot more variables you can check ie..

HOST_URI (If there are static atributes about it to check)

HTTP_USER_AGENT (Same session different values)

So all Im saying is dont just settle for one or the other when the answer lies in a combination.

For more httaccess rewriting info see the docs-> http://httpd.apache.org/docs/2.0/misc/rewriteguide.html

Some Stacks here -> https://stackoverflow.com/questions/4398951/force-ssl-https-using-htaccess-and-mod-rewrite
and
https://stackoverflow.com/questions/2236873/getting-the-full-url-of-the-current-page-php
to name a couple.

Solution 10 - Php

Use $_SERVER['HTTPS'] to tell if it is SSL, and redirect to the right place if not.

And remember, the page that displays the form does not need to be fed via HTTPS, it's the post back URL that needs it most.

Edit: yes, as is pointed out below, it's best to have the entire process in HTTPS. It's much more reassuring - I was pointing out that the post is the most critical part. Also, you need to take care that any cookies are set to be secure, so they will only be sent via SSL. The mod_rewrite solution is also very nifty, I've used it to secure a lot of applications on my own website.

Solution 11 - Php

If you want to use PHP to do this then this way worked really well for me:


<?php

if(!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != "on") {
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"], true, 301);
    //Prevent the rest of the script from executing.
    exit;
}
?>

It checks the HTTPS variable in the $_SERVER superglobal array to see if it equal to “on”. If the variable is not equal to on.

Solution 12 - Php

Don't mix HTTP and HTTPS on the same page. If you have a form page that is served up via HTTP, I'm going to be nervous about submitting data -- I can't see if the submit goes over HTTPS or HTTP without doing a View Source and hunting for it.

Serving up the form over HTTPS along with the submit link isn't that heavy a change for the advantage.

Solution 13 - Php

If you use Apache or something like LiteSpeed, which supports .htaccess files, you can do the following. If you don't already have a .htaccess file, you should create a new .htaccess file in your root directory (usually where your index.php is located). Now add these lines as the first rewrite rules in your .htaccess:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

You only need the instruction "RewriteEngine On" once in your .htaccess for all rewrite rules, so if you already have it, just copy the second and third line.

I hope this helps.

Solution 14 - Php

Using this is NOT enough:

if($_SERVER["HTTPS"] != "on")
{
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit();
}

If you have any http content (like an external http image source), the browser will detect a possible threat. So be sure all your ref and src inside your code are https

Solution 15 - Php

I have been through many solutions with checking the status of $_SERVER[HTTPS] but seems like it is not reliable because sometimes it does not set or set to on, off, etc. causing the script to internal loop redirect.

Here is the most reliable solution if your server supports $_SERVER[SCRIPT_URI]

if (stripos(substr($_SERVER[SCRIPT_URI], 0, 5), "https") === false) {
	header("location:https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
	echo "<meta http-equiv='refresh' content='0; url=https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]'>";
	exit;
}

Please note that depending on your installation, your server might not support $_SERVER[SCRIPT_URI] but if it does, this is the better script to use.

You can check here: Why do some PHP installations have $_SERVER['SCRIPT_URI'] and others not

Solution 16 - Php

For those using IIS adding this line in the web.config will help:

<httpProtocol>
    <customHeaders>
        <add name="Strict-Transport-Security" value="max-age=31536000"/>
    </customHeaders>
</httpProtocol>
<rewrite>
    <rules>
        <rule name="HTTP to HTTPS redirect" stopProcessing="true">
              <match url="(.*)" />
              <conditions>
                 <add input="{HTTPS}" pattern="off" ignoreCase="true" />
              </conditions>
              <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
         </rule>
    </rules>
</rewrite>

A full example file

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpProtocol>
            <customHeaders>
                <add name="Strict-Transport-Security" value="max-age=31536000"/>
             </customHeaders>
        </httpProtocol>
        <rewrite>
            <rules>
                <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                      <match url="(.*)" />
                      <conditions>
                         <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                      </conditions>
                      <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
                 </rule>
            </rules>
       </rewrite>
   </system.webServer>
</configuration>

Solution 17 - Php

if(location.protocol!=='https:'){location.replace(`https:${location.href.substring(location.protocol.length)}`);}

Solution 18 - Php

You shouldn't for security reasons. Especially if cookies are in play here. It leaves you wide open to cookie-based replay attacks.

Either way, you should use Apache control rules to tune it.

Then you can test for HTTPS being enabled and redirect as-needed where needed.

You should redirect to the pay page only using a FORM POST (no get), and accesses to the page without a POST should be directed back to the other pages. (This will catch the people just hot-jumping.)

http://joseph.randomnetworks.com/archives/2004/07/22/redirect-to-ssl-using-apaches-htaccess/

Is a good place to start, apologies for not providing more. But you really should shove everything through SSL.

It's over-protective, but at least you have less worries.

Solution 19 - Php

maybe this one can help, you, that's how I did for my website, it works like a charm :

$protocol = $_SERVER["HTTP_CF_VISITOR"];

if (!strstr($protocol, 'https')){
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit();
}

Solution 20 - Php

As an alternative, you can make use of X-Forwarded-Proto header to force a redirect to HTTPS.

add these lines in the .htaccess file

### Force HTTPS
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Solution 21 - Php

I have used this script and it works well through the site.

if(empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == "off"){
    $redirect = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    enter code hereheader('HTTP/1.1 301 Moved Permanently');
    header('Location: ' . $redirect);
    exit();
}

Solution 22 - Php

<?php 
// Require https
if ($_SERVER['HTTPS'] != "on") {
    $url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
    header("Location: $url");
    exit;
}
?>

That easy.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWikiView Question on Stackoverflow
Solution 1 - PhpAdam RosenfieldView Answer on Stackoverflow
Solution 2 - PhpthebigjcView Answer on Stackoverflow
Solution 3 - PhpJacob SwartwoodView Answer on Stackoverflow
Solution 4 - PhpMatHatrikView Answer on Stackoverflow
Solution 5 - PhpJayView Answer on Stackoverflow
Solution 6 - PhpJeffView Answer on Stackoverflow
Solution 7 - PhpsyvexView Answer on Stackoverflow
Solution 8 - PhpitsazzadView Answer on Stackoverflow
Solution 9 - PhpJSGView Answer on Stackoverflow
Solution 10 - PhpDGMView Answer on Stackoverflow
Solution 11 - PhpsquiremaldoonView Answer on Stackoverflow
Solution 12 - PhpJBBView Answer on Stackoverflow
Solution 13 - PhpAntonioView Answer on Stackoverflow
Solution 14 - Phpbourax webmasterView Answer on Stackoverflow
Solution 15 - PhpTarikView Answer on Stackoverflow
Solution 16 - PhpTschallackaView Answer on Stackoverflow
Solution 17 - PhpMRRajaView Answer on Stackoverflow
Solution 18 - PhpKent FredricView Answer on Stackoverflow
Solution 19 - PhpHéouais MongarsView Answer on Stackoverflow
Solution 20 - PhpSumithranView Answer on Stackoverflow
Solution 21 - PhpEsteban GallegoView Answer on Stackoverflow
Solution 22 - PhpSpellView Answer on Stackoverflow