Welcome Guest, Not a member yet? Register   Sign In
SSL in CodeIgnitor
#1

[eluser]got 2 doodle[/eluser]
First off, if you are trying to implement SSL in CodeIgnitor here are a few existing threads.
SSL, how to
https for only some views
problems with ssl in CI

None of these solutions seemed to work the way I thought they should.

modify .htaccess was too specific
force_ssl() changed all of my anchor() by modifying the base url

For reference here is the force_ssl() helper - thanks to nevercraft for this one.

Code:
/*
| Simply call force_ssl() from within any controller method (or the constructor).  
| The user will be redirected to https:// if needed.  
| Also, https:// will show up correctly on any of the other URL helpers used AFTER force_ssl() is called.
*/
if ( ! function_exists('force_ssl'))
{
    function force_ssl($controller)
    {
        $CI =& get_instance();
        $CI->config->config['base_url'] = str_replace('http://', 'https://', $CI->config->config['base_url']);
        if ($_SERVER['SERVER_PORT'] != 443)
        {
            redirect($CI->uri->uri_string());
        }
    }
}

In my case I wanted only some anchors to point to a secure page, so why not define a secure_base_url as well as a base_url.

This approach should work with shared ssl but it hasn't been tested at all. I was hoping some of the more experienced folk could comment on this approach pros and especially cons.

Here's how it works

modify /system/application/config/config.php
Code:
|--------------------------------------------------------------------------
| Base Site URL
|--------------------------------------------------------------------------
|
| URL to your CodeIgniter root. Typically this will be your base URL,
| WITH a trailing slash:
|
|    http://www.your-site.com/
|
*/
//$config['base_url']    = "http://localhost/local_folder/";
$config['base_url'] = "http://".$_SERVER['SERVER_NAME'];
$config['base_url'] .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);

//$config['secure_base_url']    = "http://localhost/local_folder/";
$config['secure_base_url'] = "https://".$_SERVER['SERVER_NAME'];
$config['secure_base_url'] .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);

extend config library - create the following file /system/application/libraries/MY_Config.php

Code:
if (!defined('BASEPATH')) exit('No direct script access allowed');
class MY_Config extends CI_Config {

    /**
     * Secure Site URL
     *
     * @access    public
     * @param    string    the URI string
     * @return    string
     */        
    function secure_site_url($uri = '')
    {
        if (is_array($uri))
        {
            $uri = implode('/', $uri);
        }
        
        if ($uri == '')
        {
            return $this->slash_item('secure_base_url').$this->item('index_page');
        }
        else
        {
            $suffix = ($this->item('url_suffix') == FALSE) ? '' : $this->item('url_suffix');        
            return $this->slash_item('secure_base_url').$this->slash_item('index_page').preg_replace("|^/*(.+?)/*$|", "\\1", $uri).$suffix;
        }
    }
    
}



continued in next post
#2

[eluser]got 2 doodle[/eluser]
extend url helper - create the following file /system/application/helpers/my_url_helper.php

Code:
if (!defined('BASEPATH')) exit('No direct script access allowed');    
/**
* Secure Site URL
*
* Create a local URL based on your secure basepath. Segments can be passed via the
* first parameter either as a string or an array.
*
* @access    public
* @param    string
* @return    string
*/    
if (! function_exists('secure_site_url'))
{
    function secure_site_url($uri = '')
    {
        $CI =& get_instance();
        return $CI->config->secure_site_url($uri);
    }
}
    
// ------------------------------------------------------------------------

/**
* Secure Base URL
*
* Returns the "secure_base_url" item from your config file
*
* @access    public
* @return    string
*/    
if (! function_exists('secure_base_url'))
{
    function secure_base_url()
    {
        $CI =& get_instance();
        return $CI->config->slash_item('secure_base_url');
    }
}
    
// ------------------------------------------------------------------------
/**
* Secure Anchor Link
*
* Creates an anchor based on the local URL.
*
* @access    public
* @param    string    the URL
* @param    string    the link title
* @param    mixed    any attributes
* @return    string
*/    
if (! function_exists('secure_anchor'))
{
    function secure_anchor($uri = '', $title = '', $attributes = '')
    {
      
        $title = (string) $title;
    
        if ( ! is_array($uri))
        {
        
            $secure_url = ( ! preg_match('!^\w+://!i', $uri)) ? secure_site_url($uri) : $uri;
        }
        else
        {
        
            $secure_url = secure_site_url($uri);
        }
    
        if ($title == '')
        {
            $title = $secure_url;
        }

        if ($attributes == '')
        {
            $attributes = ' title="'.$title.'"';
        }
        else
        {
            $attributes = _parse_attributes($attributes);
        }

        return '<a href="'.$secure_url.'">'.$title.'</a>';
    }
}

/**
* Secure Header Redirect
*
* Header redirect in two flavors
*
* @access    public
* @param    string    the URL
* @param    string    the method: location or redirect
* @return    string
*/
if (! function_exists('secure_redirect'))
{
    function secure_redirect($uri = '', $method = 'location')
    {
        switch($method)
        {
            case 'refresh'    : header("Refresh:0;url=".secure_site_url($uri));
                break;
            default            : header("Location: ".secure_site_url($uri));
                break;
        }
        exit;
    }
}

continued in next post
#3

[eluser]got 2 doodle[/eluser]
extend form helper - create the following file /system/application/helpers/my_form_helper.php

Code:
if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Secure Form Declaration
*
* Creates the opening portion of the form.
*
* @access    public
* @param    string    the URI segments of the form destination
* @param    array    a key/value pair of attributes
* @param    array    a key/value pair hidden data
* @return    string
*/    
if (! function_exists('secure_form_open'))
{
    function secure_form_open($action = '', $attributes = array(), $hidden = array())
    {
        $CI =& get_instance();

        $action = ( strpos($action, '://') === FALSE) ? $CI->config->secure_site_url($action) : $action;

        $form = '&lt;form action="'.$action.'"';
    
        if ( ! isset($attributes['method']))
        {
            $form .= ' method="post"';
        }
    
        if (is_array($attributes) AND count($attributes) &gt; 0)
        {
            foreach ($attributes as $key => $val)
            {
                $form .= ' '.$key.'="'.$val.'"';
            }
        }
    
        $form .= '>';

        if (is_array($hidden) AND count($hidden > 0))
        {
            $form .= form_hidden($hidden);
        }
    
        return $form;
    }
}
/*
|--------------------------------------------------------------------------
| Notes Caveats
|--------------------------------------------------------------------------
| Caching: Although it would be ilogical to do so caching a secure page
| would probably break the system.  Probably code should be put in place
| to prevent caching https: pages.
|
|
*/

sorry for the stupidly long post!
I could tolerate some suggestions for this also
#4

[eluser]got 2 doodle[/eluser]
Ok

so now we have
secure_anchor()
secure_form_open()
secure_redirect()
#5

[eluser]BarnabasK[/eluser]
This is absolutely awesome, thanks for the great code. Nice work.
#6

[eluser]got 2 doodle[/eluser]
Just a little addendum to this

Since I develop on a windows box and I hadn't tested this out live until today.

My host is Linux and therefore case sensitive.

Make sure that the helpers and libs. are named 'MY_url_helper.php' and 'MY_form_helper.php' and 'MY_Config.php'

So far I tested it with a shared SSL certificate, this is a case were simply changing 'http' to 'https' is not good enough. Using this method you can define the ugly shared ssl url.

Example unsecure url 'http:\\mydomain.com\sbx1'
Shared ssl (my host) 'https:\\mydomain.sslpowered.com\mydomain.com\sbx1'

I haven't yet set up an .htaccess to remove the index.php, there could be problems there.

doodle
#7

[eluser]got 2 doodle[/eluser]
OK, It's a it weird that I'm basically the only one posting to this thread, but I think a few people have read the post and hopefully got some value out of it.

Now I need some help from the guru's on this board to take things to the next step.

The site is up and running, I have SSL where I want it and due to a fluke error on the whois information for the site, the administrative contact information is incorrect so the dedicated ssl certificate cannot be administered at this time (once the client sorts their end out all will be cool). Anyway so now the site is using shared ssl, at least I know it works.

I am having problems with the .htaccess removing the index.php (ya ya, heard it all before I hear you cry!)

I can remove the index.php with the .htaccess file submitted by Elliot Haughin no problems until I try the secure url.

here is the .htaccess
Quote:<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# The Friendly URLs part
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>

<IfModule !mod_rewrite.c>
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
# Submitted by: ElliotHaughin

ErrorDocument 404 /index.php
</IfModule>

all pretty normal stuff

also in config/config.php
Code:
$config['index_page'] = "";

this works no problem until I try a secure URL
Locally everything works with stripping out index.php for http: and https: but remote server is a no go on the shared ssl connection.

this is a portion of my config/config.php that defines the base_url and secure_base_url
Code:
$setup = 'remote'; // local or remote
switch ($setup) {
case 'local';
    $config['index_page'] = "";
    $config['base_url'] = "http://".$_SERVER['SERVER_NAME'];
    $config['base_url'] .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);
    $config['secure_base_url'] = "https://".$_SERVER['SERVER_NAME'];
    $config['secure_base_url'] .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);
break;
case 'remote';
    $config['index_page'] = "index.php";
    $config['base_url']    = "http://www.tatacentre.ca/";
    $config['secure_base_url']    = "https://www.tatacentre.sslpowered.com/tatacentre.ca/";
break;
}
For now index.php is left in there for the remote configuration.

I have determined that mod_rewrite is working on the remote server but my secure links only work if I leave the index.php in there.

Any suggestions???

aaaaaa!!
doodle :-S
#8

[eluser]got 2 doodle[/eluser]
OK, I'm back to posting to my thread. The dedicated ssl certificate has been configured and installed. Now I can remove the index.php with a simple .htaccess file (I couldn't figure out how to deal with the shared ssl configuration in the .htaccess)

Anyway a new quirk has popped up, In my registration controller I was checking that the connection was actually secure by checking the port number. I wanted to guarantee that there was no way the form could be shown if the connection was not secure. I also needed to know how the user came to be at the registration controller, ie: have they selected a product yet or do we give them a choice of products. Up until the dedicated certificate was installed I just checked for port 443 but now the port number is 12198 so I check for either possible port. I have asked my hosting company if the port will always be the same. Here's the code that checks the port.
Code:
// check if this is by program
    if(isset($_POST['by_program'])) {
         if( $_SERVER['SERVER_PORT'] == '443' or $_SERVER['SERVER_PORT'] == '12198'){
            $program_id = $_POST['program'];
            secure_redirect('/register/program/'.$program_id.'/', 'refresh');
                     } else {    secure_redirect('/register/', 'refresh') ;}
                     } else {
    // not by program    
            if( !$_SERVER['SERVER_PORT'] == '443' or !$_SERVER['SERVER_PORT'] == '12198'){    secure_redirect('/register/', 'refresh') ;}    
                     }
                
    // no program selected                
    if($this->uri->segment(3) == '') { secure_redirect('/register/', 'refresh'); }
so this is working but only on two ports (443 and 12198)

Does anyone know about this port 12198 thing!!

Also I made a change that makes it easier to work between local and remote installations.

I set a constant in index.php
Code:
/*
|---------------------------------------------------------------
| DEFINE APPLICATION CONSTANTS
|---------------------------------------------------------------
|
| EXT        - The file extension.  Typically ".php"
| FCPATH    - The full server path to THIS file
| SELF        - The name of THIS file (typically "index.php)
| BASEPATH    - The full server path to the "system" folder
| APPPATH    - The full server path to the "application" folder
|
*/
define('SERVER_LOCATION','local'); /* local or remote */ <--- new constant
define('EXT', '.'.pathinfo(__FILE__, PATHINFO_EXTENSION));
define('FCPATH', __FILE__);
define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME));
define('BASEPATH', $system_folder.'/');

My thinking was that index.php rarely changes once it's been uploaded to the server.

Now in config/config.php
Code:
/*
|--------------------------------------------------------------------------
| Base Site URL
|--------------------------------------------------------------------------
|
| URL to your CodeIgniter root. Typically this will be your base URL,
| WITH a trailing slash:
|
|    http://www.your-site.com/
|
*/
switch (SERVER_LOCATION) {
case 'local';
    $config['index_page'] = "";
    $config['base_url'] = "http://".$_SERVER['SERVER_NAME'];
    $config['base_url'] .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);
    $config['secure_base_url'] = "https://".$_SERVER['SERVER_NAME'];
    $config['secure_base_url'] .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);
break;
case 'remote';
    $config['index_page'] = "";
    $config['base_url']    = "http://tatacentre.ca/";
    $config['secure_base_url']    = "https://tatacentre.ca/";
break;
}
Just thought I would share this last bit, so far it seems like a good idea.

doodle
#9

[eluser]rbdc[/eluser]
love this! testing it out now and seems to work exactly as expected and wanted
#10

[eluser]Rick Jolly[/eluser]
A couple of comments:

1) To avoid your problem with multiple secure ports, instead of using the server port ($_SERVER['SERVER_PORT']), use $_SERVER['HTTPS'].
Code:
// example:
$protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';


2)Instead of essentially duplicating the base_url(), site_url(), and redirect() just to add an "s" to "http", override them to add an optional "protocol" parameter. I won't comment on anchor() or form_open() since I don't use them.

Edit:
3)By default, if the current protocol is https, then the base_url should be https as well. That way all images, js, and css includes will use https by default and you'll avoid warnings in IE. Exceptions for unsecure site links can be made by specifying http protocol in the overriden url helper methods above. There shouldn't be a need for a "secure_base_url" config value.
Code:
// example:
$config['protocol'] = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
$config['base_url'] = $config['protocol'] . '://your-site.com/';

// and your base_url method could look like this:
function base_url($protocol = false)
{
  $CI =& get_instance();
  $base_url = $CI->config->slash_item('base_url');
  if (($protocol) AND ($pos = strpos($base_url, '://')))
  {
     $base_url= $protocol . substr($base_url, $pos);
  }
  return $base_url;
}

CI should seperate the protocol from base_url in the config imo.




Theme © iAndrew 2016 - Forum software by © MyBB