Force page to break out of secure protocol (https:// > http://) - php

I used info from this answer (https://stackoverflow.com/a/85867/3271766 - along with the contribution from Dave1010) to allow me to force a page to load securely (https://). This works beautifully!
Now, I want to do the opposite. When clicking a relative link (to a normal, non-secure page) from a secure page, I want to force that page to load non-securely (http://). I don't want to use absolute links to accomplish this. They need to stay relative. Instead, I'd rather use a piece of PHP code similar to what I used to force pages to load securely.
How can this be done? Thanks, in advance, for your help.
The code I used (in each page's head tags) to force pages to load securely is:
<?php
// WORKING: FORCE SECURE - Force page to load securely (http:// > https://)
if(empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on")
{
header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
exit();
}
?>
I tried the following, but it stops the page from loading altogether:
<?php
// NOT WORKING: FORCE NON-SECURE - Force page to break out of secure protocol (https:// > http://)
if(empty($_SERVER["HTTP"]) || $_SERVER["HTTP"] !== "on")
{
header("Location: http://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
exit();
}
?>
Is there a way to modify this to make it work?
(By the way, in case anyone is wondering, I am doing this because a third-party sharing tool my client wants to use does not have a valid security certificate. Thus, portions of the sharing tool either do not load, or do not function. I have contacted the vendor repeatedly, but they have not responded. I have removed the tool from the secure pages only. However, my client wants to use this tool on all other pages, on which it works perfectly, so long as it is not accessed securely.) :-)
Regards,
Jeremy

Change
if(empty($_SERVER["HTTP"]) || $_SERVER["HTTP"] !== "on")
to
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'){
$url = 'http://'. $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
header("Location: $url");
}

Related

How do I Force Users to http only on Certain Pages ? (PHP)

In my case.. I want only demo.com/watch/MOVIE_NAME to be redirected to HTTP. Otherwise, all the pages will remain in https.
The reason for using HTTP on /watch page is--> My website contents are hosted on a non-ssl server. And we cant serve that on a secured page(https). That's why I needed to /watch page redirect to HTTP.
I tried to use this code..But it shows too many redirects.
<?php
if($_SERVER["HTTPS"] = "on")
{
header("Location: http://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
exit();
}
?>
Am I doing anything wrong..Is there a simple way to do this... Please, Let me know.
& Sorry for the questions, but my searches thus far here, I haven't revealed a working solution, and I'm afraid I don't know what the best practice is.

PHP redirect to HTTPS if page is

I need a PHP if/else statement that if the sign-in.php or register.php page is access over HTTP I would like to redirect to HTTPS else if any other page is accessed over HTTPS redirect to HTTP plus have any query string appended for example if a user tries to access a restricted page (http://domain.com/my-account.php) the site redirects the user to http://domain.com/sign-in.php?redirect=my-account however, I would like the page to redirect to https://domain.com/sign-in.php?redirect=my-account.
I know I could simply change the header redirects to include https instead of http but users may type http://domain.com/sign-in.php?redirect=my-account so just need to ensure if this happens sign in (or others) happen over https.
Any help is appreciated
Here You go.
//force the page to use ssl
if ($_SERVER["SERVER_PORT"] != 443) {
$redir = "Location: https://" . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header($redir);
exit();
}
$_SERVER, It is an array containing information such as headers, paths, and script locations.
You can check against $_SERVER, specifically 'SERVER_PROTOCOL'
http://php.net/manual/en/reserved.variables.server.php
There should be a part of your code that is always run on every page. In an MVC it would be in your base controller. Other designs may include an init.php file on every page.
In this file have a whitelist of pages that require HTTPS.
$requires_https = array(
'sign-in.php' => TRUE,
'register.php' => TRUE
);
Then you need to determine which page was requested.
$url_info = pathinfo($_SERVER['REQUEST_URI']);
$page = $url_info['filename'];
Next check if you are on HTTP or HTTPS
$is_secure = ! empty($_SERVER['HTTPS']);
Finally you can do the checking:
if (isset($requires_https[$page]) AND ! $is_secure)
header('Location: https://www.yoursite.com/' . $page);
elseif ( ! isset($requires_https[$page]) AND $is_secure)
header('Location: http://www.yoursite.com/' . $page);
This could definitely be improved upon in the last part by using a custom redirect function and a site_url function that takes in the option of being secure or not and builds the proper URL.
It is worth mentioning that it generally doesn't matter if someone is left surfing in HTTPS. In fact most of Google's services are in HTTPS and with better internet connections surfing will eventually all be done in HTTPS. It is only important to make sure the pages that should be secure are secure, not make sure that pages that don't need to be secure aren't.
if ($_SERVER['SERVER_PORT'] != 443) {
header("HTTP/1.1 301 Moved Permanently");
header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
exit();
}
Using part of an init class / script -
You can run code to check if this page should require SSL prior, but this is the actual code to force redirect to SSL (and REQUEST_URI provides any dirs, etc.. to get the correct path).
Using on a single page (i.e. sign-in and register) -
This will redirect the user to this page in SSL (put this code near the top).
The 301 Moved Permanently will also prevent any negative SEO.
(A more) complete method: (includes the query string)
To determine if on https:
$secure = (!empty(filter_input(INPUT_SERVER, 'HTTPS')) &&
filter_input(INPUT_SERVER, 'HTTPS') !== 'off') ||
filter_input(INPUT_SERVER, 'SERVER_PORT') == 443;
as per https://stackoverflow.com/a/2886224
Then to redirect and include the query string:
if($secure){
header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
}
Using REQUEST_URI instead of PHP_SELF will include the query parameters (things after the ? in the URL).
And as always filter your user input (including these) with filter_input() or the like.

Weird behavior in IE/Firefox regarding $_SERVER['QUERY_STRING']

In an php-based application I've been coding, I have the following small block of code:
if (isset($_SERVER['QUERY_STRING'])) {
header("Location: " . $_SERVER['QUERY_STRING']);
}
In my application, I use framesets and frames. This code is present in the main content area frame, and upon execution in IE, creates an infinite loop which kills the browser unless I manually stop loading.
The purpose of this code is to detect if there is a query string appended to the url, and if so, redirect to that query string. I've primarily been developing using chrome and and firefox, and today decided to test it in IE9. I have not tested it in any previous versions, but so far this behavior only occurs in IE, and I'm frankly stumped on why such is happening. I've searched for similar questions here and on the internet, but so far no dice.
Edit
As I noted with an earlier edit, I am using framesets and frames to control the interface. The left-hand frame, a side bar, contains links with a base target of the main 'content' area frame. The content of the content area frame contains javascript that appends a query string to the parent window's url, so that when the index page is visited(with the query string present), it will redirect the content frame to that specific page.
This works perfectly fine in Chrome. Not IE(or firefox, which I just discovered as of this edit). Ie instead redirects to the index page, the page containing the frameset, and it does this forever, creating sidebar after sidebar.
Try the following:
session_start();
if ( !isset($_SESSION['Redirect'] ) && isset( $_SERVER['QUERY_STRING'] ) ) {
$_SESSION['Redirect'] = true;
header( "Location: " . $_SERVER['QUERY_STRING'] );
}
I don't know if this can be your problem at all, but as per HTTP/1.1, redirection requires the full absolute path including the hostname. So perhaps try this:
<?php
/* Redirect to a different page in the current directory that was requested */
$host = $_SERVER['HTTP_HOST'];
$uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
$extra = $_SERVER['QUERY_STRING'];
header("Location: http://$host$uri/$extra");
exit;
?>
Or another suggestion is to avoid using the full querystring (like ?thispage.php), but to use a GET parameter instead (like ?path=thispage.php).
<?php
/* Redirect to a different page in the current directory that was requested */
$host = $_SERVER['HTTP_HOST'];
$uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
$extra = $_GET['page'];
header("Location: http://$host$uri/$extra");
exit;
?>
I kind of hate myself for not thinking of this sooner, given how horribly simple it is. All I did, was check if $_SERVER['QUERY_STRING'] was empty, as so:
if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '') {
header("Location: " . $_SERVER['QUERY_STRING']);
}
And that solved the problem of the index page creating infinite nested framesets and frames.

Trouble redirecting to HTTPS with PHP

I just had an ssl installed for a site I am working on and I obviously need to get a few of the pages (checkout etc) redirected to https.
I am currently using this code:
if (!isset($_SERVER['HTTPS']) || !$_SERVER['HTTPS']) {
$url = 'https://www.mysite.php';
header("location: ". $url);
exit();
}
Firefox is telling me that "the page is trying to redirect in a way that will never complete."
A var_dump of $_SERVER shows no ['HTTPS'] or similar when I am on the secure page. This is on a Network Solutions small unix package. Is it possible I need to be checking for a different server variable or perhaps I need to change some server settings?
Clearly the script is never finding HTTPS so it is trying to redirect without end.
It becomes clearer if you use OR:
if (!isset($_SERVER['HTTPS']) OR !$_SERVER['HTTPS']) {
Chances are one of the conditions always evaluates to true, even when you already are in HTTPs mode.
You want AND:
if (!isset($_SERVER['HTTPS']) AND !$_SERVER['HTTPS']) {
I use this form of SSL Checking too. For me my code works. Here is what i do.
if(empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") {
header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
}
This works great and also redirects you to the previous url.
hope this helps.

Can you carry POST variables page to page if redirecting?

To start, I am not asking if I can create a POST response from one page to another without use of a form or one of the similar questions which may come to mind. At the start of several of my pages, I automatically force https security with the following require statement:
<?php
if($port == 80) {
if($_SERVER['SERVER_PORT'] == 443) {
header('Location: http://'. $_SERVER['HTTP_HOST'] . $_SERVER["REQUEST_URI"]);
exit;
}
} elseif ($port == 443) {
if($_SERVER['SERVER_PORT'] == 80) {
header('Location: https://'. $_SERVER['HTTP_HOST'] . $_SERVER["REQUEST_URI"]);
exit;
}
}
?>
where $port is set directly before calling the PHP require. In some instances where directing from a http to https (or simply changing the URL by person), any POST variables generated from the form on page 1 would be lost on the redirect.
Maybe I am asking the same question as the 'no form' but if so, any advice on how to handle based on the requirements is appreciated.
Thoughts
I could put everything into SESSION but this seems like a huge waste of resources. Unless somebody can really show otherwise, I don't consider this a solution.
I've seen other questions that ask essentially the same question, and I believe it's not really possible to do what you want effectively. My own opinion is it's going to be a whole lot MORE work to make what you want than just to deploy SESSION:
<?php
session_start();
if (!is_array($_SESSION['posted'])) {
$_SESSION['posted'] = array('test'=>'test');
} else {
$_POST = $_SESSION['posted'];
unset($_SESSION['posted']);
}
echo '<pre>';
echo "<strong>POST:</strong>\n";
print_r($_POST);
echo "\n";
echo "<strong>SESSION:</strong>\n";
print_r($_SESSION);
?>
* Note: I don't have SSL setup on my server, so I can't demonstrate that specifically. This is meant to demonstrate reinflating a POST array only from a SESSION-stored array.
http://jfcoder.com/test/postsession.php (Refresh to see it change.)
So if you can rebuild a POST array so easily^, why not just do that? The resources needed to do it across requests that are needed and actually used I believe will be negligible, since you're really only doing it for a moment.
Unless you have hundreds of thousand or millions of concurrent hits, I can't imagine the above being a problem resource wise. If it was, then just process it before redirecting. They've already sent the data in the clear at that point anyway.
^ Also, you will need to handle file uploads as well, if you need that.
If you really don't want to do any server-side storage, use a 307 redirect. Should work with any HTTP/1.1 compliant browser... however note that not only will you be using twice the bandwidth for the POST data (since it is sent twice), but browsers are required to ask for permission before resubmitting to the new URL.
header('HTTP/1.1 307 Temporary Redirect');
header('location: .... );
[edit: Storing it server-side temporarily is probably better. Avoiding the need to redirect at all is best.]

Categories