Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Codeigniter redirect not preserving HTTPS in relative redirects

I have a site which has a public and a private area. The private area should be served via HTTPS. I want to redirect once to an explicit HTTPS url, and then, using relative URLS, have all the links be secure. When the user logs out, I will explicitly link to an absolute non-secure HTTP URL.

My login form is shown a non-secure site via regular HTTP. My login form posts to https://www.mysite.com/login/validate , which loads using a secure connection.

My logs show that Apache is loading the URL via HTTPS and codeigniter is doing its validation correctly.

At the end of my controller function I redirect to /myaccount using CodeIgniter's URL helper's redirect method with a relative URL.

redirect('/myaccount');

This causes codeigniter to redirect to a non-HTTPS URL.

My config base_url is non-HTTPS:

$config['base_url'] = "http://www.mysite.com"

This is because some parts of the site are secure while others are not.

Is there a way to tell CodeIgniter to preserve HTTPS when doing relative redirects? Why is it assuming I want to go to a non-HTTPS site if the current controller was loaded via HTTPS and I am doing a relative redirect?

The desired behavior for me is that if I am doing relative redirect, it should preserve the protocol through which the current request was loaded. Instead, it is switching to what the config base_url has defined, even for relative redirects.

like image 788
Krystian Cybulski Avatar asked Dec 03 '22 05:12

Krystian Cybulski


2 Answers

Use this:

$config['base_url'] = "http".((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") ? "s" : "")."://".$_SERVER['HTTP_HOST'].str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);

Instead of this:

$config['base_url'] = "http://www.example.com"

This'll always redirect to where you want it. You don't even have to enter your domain name, just use it as is!


In addition to the above, I also autoload this helper:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

function is_https_on()
{
    return isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
}

function use_ssl($turn_on = TRUE)
{
    $url = $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];

    if ( $turn_on )
    {
        if ( ! is_https_on() && $_SERVER['HTTP_HOST'] != 'localhost')
        {
            redirect('https://' . $url, 'location', 301 );
            exit;
        }
    }
    else
    {
        if ( is_https_on() )
        {
            redirect('http://' . $url, 'location', 301 );
            exit;
        }
    }
}

/* End of file https_helper.php */
/* Location: ./application/helpers/https_helper.php */

With this in place, I can set my individual pages to always use HTTPS/HTTP (either in a single method in my controller, or - if I want it to affect the whole controller - in the constructor).

I simply use:

use_ssl();

at the beginning of the script, to ascertain that it is loaded via HTTPS.

Alternatively, if I only want to serve it through HTTP, I'll use:

use_ssl(FALSE);
like image 192
Joseph Silber Avatar answered Jan 10 '23 02:01

Joseph Silber


There is no 'out of the box' way to handle this HTTPS / HTTP handoff in CI. What you CAN do is create a small helper (that you auto include) which will add a function like secure_url(), and quite simply returns what a base_url would, but https format.

You would have to emulate the same redirect function maybe as secure_redirect().

like image 22
Jakub Avatar answered Jan 10 '23 04:01

Jakub