How do I force HTTPS on a some pages? (PHP) - php

I have a single PHP file which handles credit card processing. It starts as a form to input the credit card number, then becomes a "confirm" screen (showing the credit card number) then once more to process and display the results. All three loads will be done with PHP submits (I realize the confirm might be better as Javascript, but I didn't write it). It is the only file in the directory which handles credit cards, and therefore it is the only one which needs httpS connection.
I have tried forcing this with the $_SERVER array, looking up the protocol used to connect from the prefix of the SCRIPT_URI (or other entry), but none had the prefix.
Is there a simple way to do this...i want ssl on 5 pages homepage, login, register, contact page and if user visit other page then he should be on non ssl version
Sorry for the questions, but my searches thus far here haven't uncovered a working solution, and I'm afraid I don't know what the best practice is.

Use this code on php pages you want:
if($_SERVER["HTTPS"] != "on")
{
header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
exit();
}

You should investigate $_SERVER['HTTPS']. This will have a non empty value if https is used and an empty value otherwise.
If you detect a non https connection you can redirect the user, e.g. using php header() method.
Another way to achieve this would be to use .htaccess configuration (if you're running on apache web server):
RewriteCond %{HTTPS} !=on
RewriteRule ^creditcard\.php$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]
Using https for the whole website is a really good option, too.

Suppose you want to redirect 4 specific pages to https,
page1.php
page2.php
page3.php
page4.php
then you would do something like this:
Create a .htaccess file in your root directory and add the following lines to it.
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
#redirect www.yourdomain.com to yourdomain.com (or any other subdomain)
RewriteCond %{HTTP_HOST} !^yourdomain.com$ [NC]
RewriteRule ^(.*)$ http://yourdomain.com/$1 [L,R=301]
#force https for certain pages
RewriteCond %{HTTPS} !=on
RewriteRule ^(page1\.php|page2\.php|page3\.php|page4\.php)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]

Related

Redirecting site for HTTPS

I am trying to redirect my site to always open in HTTPS. I am using CloudFlare and they have a setting to "Always use HTTPS". But there is a page on my website where I do not want to use HTTPS as it opens other websites under an iFrame. And if that page also loads in HTTPS then under iFrame any website whose URL hasn't been mentioned with HTTPS doesn't open. Therefore, for that particular page I want to keep the website to be opened under HTTP.
Things I am doing:
In CloudFlare Crypto settings "Always Use HTTPS" is ON.
Then in my page where I want it to opened under HTTP say surf.php
I am using the following PHP code:
if($_SERVER['HTTP_HOST'] != 'localhost'){
if(isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'on'){
if(!headers_sent()){
header("Status: 301 Moved Permanently");
header(sprintf('Location: http://%s%s',$_SERVER['HTTP_HOST'],$_SERVER['REQUEST_URI']));
exit();
}
}
}
Now the page doesn't open and says "The page isn’t redirecting properly". What should I do? Is there any other method to accomplish this? I want to use HTTPS in whole website so "Always use HTTPS" settings in cloudflare should be ON except just surf.php. What should be the best method here?
It sounds like you are in a redirect loop. Where you have a .htaccess file that forces HTTPS, and then you redirect to HTTP using PHP. Then that new request has all the same rules applied to it so that it gets redirected by .htaccess again to HTTPS, and so on (to infinity)
So I would first make sure your not forcing HTTPS in your .htaccess file. If so you can add a RewriteCond to exclude your URL:
#RewriteEngine On #-- if not included elsewhere
#if HTTPS is not on (then continue)
RewriteCond %{HTTPS} !=on
#add this rule in (if not our page, then redirect to HTTPS)
RewriteCond %{REQUEST_URI} !^/surf\.php$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
When mod rewrite hits a Rewrite condition if it fails (is false) it will disregard the next rewrite rule. So with this in place your PHP code could do it's job, but you can also do this in htaccess alone. Because you will have dependence on the URL in there anyway, I don't see an issue doing it all in the .htaccess file.
This would basically be the opposite of the above except you know the url. Something like this:
#if HTTPS is not on (then continue)
RewriteCond %{HTTPS} !=on
#add this rule in (if not our page, then redirect to HTTPS)
RewriteCond %{REQUEST_URI} !^/surf\.php$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
#if HTTPS is not off (then continue)
RewriteCond %{HTTPS}!=off
# (if is our page, then redirect to HTTP)
RewriteCond %{REQUEST_URI} ^/surf\.php$
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
I can't really test this though, but that's the general idea. If HTTPS is no off, and the %{REQUEST_URI} is our page !^/surf.php$ redirect to HTTP... Basically you have to punch a hole through the HTTPS rule and then force http.
I am pretty sure with %{REQUEST_URI} you only have to check if it starts with your URL (minus the host and protocal).
I'll admit I'm a bit rusty with complex HTACCESS rules, spoiled by MVC routers, so this may very well not be 100% correct. But the general idea is sound.
Anyway hope it helps.

How to implement site-wide SSL leaving index.html alone using .htaccess?

Currently I am using the following at the beginning of my root's .htaccess file. Is there a safe way to exclude index.html? Is this even necessary?
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Everything on the site should be secured except the initial index.html page. The site is a very simple service with one landing page, 3 registration pages (requiring ssl), and logged in mode (again requiring ssl). Other than a few UI graphics, there is no major downloading of files. The service is mostly textual once logged in.
The only reason I ask is that many threads on here suggest that having SSL enabled on the entire site is not a good idea. It seems that since I only have one "landing page" and everything else needs to be secured, I may have the exception to this rule? Any potential issues just leaving SSL for the index as well?
Thanks for any thoughts
Add another condition:
RewriteCond %{REQUEST_URI} !^/(index\.html)?$
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Force users to access my page over HTTPS instead of HTTP?

Follow up question to what is posted here:
How can I force users to access my page over HTTPS instead of HTTP?
I've added the following code to one page, the index.php page of my CART directory.
if($_SERVER["HTTPS"] != "on")
{
header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
exit();
}
When I browse the site starting from the index page, all files within the CART directory are loaded through HTTPS (which I actually want), but if I click a link to a another page outside the CART folder, it goes back to HTTP.
How is this working this way? How is the HTTPS staying active for pages within the CART directory? If I type in a URL for a page within the CART directory, HTTPS is not enforced, which makes sense.
The site URL is http://wtc.betaforming.com
Trying to wrap my brain around this, thanks.
Brett
I would recommend adding this bit of code to your .htaccess file (if your running Apache) in your root directory.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} =off
RewriteRule ^DIRECTORY1|DIRECTORY2|DIRECTORY3 https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} =on
RewriteCond %{REQUEST_URI} !^/DIRECTORY1|DIRECTORY2|DIRECTORY3
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
Where you replace DIRECTORY1,DIRECTORY2, etc. with the directories that you want to force HTTPS on, then doing it in reverse (the code just below), by saying if not DIRECTORY1,DIRECTORY2, etc. then redirect to HTTP.
Hope this helps
You answered your own questions in your question:
How is this working this way? How is the HTTPS staying active for pages within the CART directory?
...when you said:
I've added the following code to one page, the index.php page of my CART directory.
See? You're enforcing HTTPS requirement for pages in your cart directory, but not elsewhere. Which reflects what you're seeing on your site. If you want to require HTTPS site-wide, considering using your webserver to enforce that requirement. For example with Apache and mod_rewrite you might try something like this:
<IFModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</IFModule>
EDIT
In a comment in your post you say "I'm trying to understand how/why HTTPS is being enforced when browsing to other pages in the CART directory from the index.php page". My guess (and it is a guess since you have not shown us your code) is that those URLs are built in a ssl-agnostic way, like this:
I'm SSL-enabled on a page with HTTPS in the address bar
Again though, without seeing your code, it's impossible to say.
Cheers
<?php
// Require https
if ($_SERVER['HTTPS'] != "on") {
$url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
header("Location: $url");
exit;
}
?>
Try to add this on the file you're trying to access in HTTPS and it will force the browser to load in HTTPS.

Changing of www makes session expire

I have a merchant website linked to a bank.
I have defined this success URL in bank :
http://www.mydomain.com/deposit.php
When the user starts payment process he enters to bank website and after payment he redirects to the success URL in my website.
If a user enters my website with this URL (without www) :
http://mydomain.com/
The session expires and he should login again. but when he enters with this URL :
http://www.mydomain.com/
The session will not expire and everything is okey. how can i solve this problem?
The thing is your session cookie is probably specifically tied to www.mydomain.com, so, when you access mydomain.com, the browsers chooses not to send the session cookie.
Take a look at ini_set function, and the session.cookie_domain value.
if (count(explode('.', $domain)) > 2) {
ini_set('session.cookie_domain', $domain);
}
You can force www. (or force using just http://mydomain.com aswell) using the .htaccess file.
RewriteCond %{HTTP_HOST} !^www.mydomain\.com [NC]
RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R]
The ! in the RewriteCondition tells the server that when the address does NOT equal the following, redirect it to the RewriteRule.
You can find alot more Rewrite tips 'n tricks using .htaccess on the web.
Note: For this to work, you will need to enable this first in your .htaccess file:
RewriteEngine On
And make sure your Apache (or other host) configuration supports mod_rewrite.
Taken from the HTML5 Boilerplate .htaccess:
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
Placing that in your .HTACCESS file should fix the problem. However, someone else will have to elaborate on what exactly is the cause of this problem.
Edit: Seems to me like Pablo Santa Cruz is right.

Displaying update page once

I am in the middle of developing a new website with my existing site still up and running. What I want to do is redirect the user to an update page when they visit the existing site (regardless of what page they enter on) then redirect them from that update page to the original page they requested.
I think the mod_rewrite rule would look something like
RewriteEngine On
# redirect to landing page
RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1 // my real IP would go here
RewriteCond %{REQUEST_URI} !/UpdatePage.html$ [NC] // stop infinite loops on itself
RewriteRule .* /UpdatePage.html [R=302,L]
So the above would achieve redirecting the user from any page to the update page. However, evidently the issue here is it is going to cause a continuous loop...
I imagine I need some form of flag here? I am not really too experienced with Mod_Rewrite is something like this possible? Or is this something that can be achieved outside of Mod_Rewrite with pure PHP?
Edit: I had a chance to play with my htaccess file and I did figure out a solution that I have appended below. Long story short though, I wouldn't use it even though it seems to work.
Original:
You can try not redirecting if you have already redirected by adding the REDIRECT_STATUS check:
RewriteEngine On
# redirect to landing page
RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1 // my real IP would go here
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteCond %{REQUEST_URI} !/UpdatePage.html$ [NC] // stop infinite loops on itself
RewriteRule .* /UpdatePage.html [R=302,L]
From what I understand this would mean: redirect to the UpdatePage.html if the remote address is a certain IP address and it has not been redirected before.
I'm unable to check whether this will result in the desired behaviour, but I did get this from the answer on this SO question: Clean URL Redirect Loop.
Tested solution:
I played around with my WAMP setup and came up with this:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1 // my real IP would go here
RewriteCond %{REQUEST_URI} !/UpdatePage.html$ [NC] // stop infinite loops on itself
RewriteCond %{REQUEST_URI} ^(.+)\.html$ [NC] // Only handle html pages
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^(.+)\.html$ [NC] //don't redirect if the referer is a page. Should actually include the domain as well
RewriteRule .* /UpdatePage.html [R=302,L]
The first time to any html page in the site should redirect to the UpdatePage then the user would click a link on that page and will go to the original page. The referer environment variable is then set and you can check if it is valid and then not redirect.
This does not handle going to the root of the website. The user must be loading an html page directly.
I much prefer your solution (#james). Coding the logic into the top of the main gateway PHP page is simpler and far less error prone, but I figured I would try to find a way using htaccess :-). Please note that I would never use this particular htaccess method myself.
Due to the way the current site is implemented (everything goes through index.php page) I was able to simply use some session variables in order to detect whether the user should be redirected to the update page or not e.g.
<?php
if (!isset($_SESSION['ShowUpdatePage']) || $_SESSION['ShowUpdatePage'] == "true")
{
$_SESSION['ShowUpdatePage'] = "false";
header("Location: UpdatePage.html");
}
?>
This also means that they will only ever get redirected once per session which is exactly what I was looking for.
In my opinion this is the best way to go about it:
real site: www.example.org
old site: old.example.org
new site: new.example.org
The 'new.' domain needs to be in place well beforehand. When you cut over the site you can just redirect everybody hitting the old site to new.example.org. For a while your users will have the 'incorrect' domain. After a few days you can redirect "new." to "www.".

Categories