This is an auto-response so other people can find a possible method to
solve this.

The idea was to allow certain actions (such as any action within the
Account controller) to *only* be accessed through SSL.

First of all, I wanted to have an array of all actions that should only
be accessed through HTTPS. So in boostrap.php I added:

$GLOBALS['AppConfig'] = array(
        'SSLActions' => array (
                'account/*'
        )
);

This means that any action within the account controler must be
accessed through SSL.

Then, I had to extend the Html helper. Now, I didn't want to make a
copy of this helper and then modify, but I wanted to inherit from it
and create my own html helper, so in the future new things could be
added and if ever the html helper gets improved i wouldn't be loosing
those improvements. So I created a new helper called SyHtml, with this
code:

require_once(CAKE_CORE_INCLUDE_PATH . DS . 'cake' . DS . 'libs' . DS .
'view' . DS . 'helpers' . DS . 'html.php');

class SyhtmlHelper extends HtmlHelper
{
        function url($url = null, $return = false)
        {
                if (isset($GLOBALS['AppConfig']) &&
isset($GLOBALS['AppConfig']['SSLActions']) && isset($url) && trim($url)
!= '')
                {
                        $current_url = ($url{0} == '/' ? substr($url, 1): $url);

                        $current_url_is_ssl = false;

                        foreach($GLOBALS['AppConfig']['SSLActions'] as 
$current_ssl_action)
                        {
                                if (strpos($current_ssl_action, '*') !== false)
                                {
                                        $current_pattern = $current_ssl_action;
                                        $current_pattern = str_replace('/', 
'\\/', $current_pattern);
                                        $current_pattern = str_replace('*', 
'(.*)', $current_pattern);

                                        $current_url_is_ssl = preg_match('/' . 
$current_pattern . '/i',
$current_url);
                                }
                                else if (strcasecmp($current_ssl_action, 
$current_url) == 0)
                                {
                                        $current_url_is_ssl = true;
                                }

                                if ($current_url_is_ssl)
                                {
                                        break;
                                }
                        }

                        if (($current_url_is_ssl && !$this->_in_ssl()) ||
(!$current_url_is_ssl && $this->_in_ssl()))
                        {
                                $url = parent::url($url, true);

                                $url = ($url{0} == '/' ? substr($url, 1): $url);

                                $current_base_url = ($current_url_is_ssl ? 
'https://' : 'http://');
                                $current_base_url .= $_SERVER['SERVER_NAME'];
                                $current_base_url .= (!$this->_in_ssl() && 
$_SERVER['SERVER_PORT']
!= 80 ? ':' . $_SERVER['SERVER_PORT']: '');

                                $url = $current_base_url . '/' . $url;

                                return $this->output($url, $return);
                        }
                }

                return parent::url($url, $return);
        }

        function _in_ssl()
        {
                return (isset($_SERVER['HTTPS']) && 
strcasecmp($_SERVER['HTTPS'],
'on') == 0 ? true : false);
        }
}

Since I'm extending the url() method, any other html helper function
that uses this method will be using our version (as long as we used the
SyHtml helper). For example, on layout.thtml I have the following:

<?php echo $syhtml->link('Login', '/account/login', array('class' =>
'login')); ?>
<?php echo $syhtml->link('Forgot', '/account/forgot'); ?>

Our helper will see that these two links should be linked to their
HTTPS version.

Finally, on the AppController class I add the following code to the
beforeRender() method:

if (isset($GLOBALS['AppConfig']) &&
isset($GLOBALS['AppConfig']['SSLActions']))
{
        $current_url = ($this->here{0} == '/' ? substr($this->here, 1):
$this->here);

        $current_url_is_ssl = false;

        foreach($GLOBALS['AppConfig']['SSLActions'] as $current_ssl_action)
        {
                if (strpos($current_ssl_action, '*') !== false)
                {
                        $current_pattern = $current_ssl_action;
                        $current_pattern = str_replace('/', '\\/', 
$current_pattern);
                        $current_pattern = str_replace('*', '(.*)', 
$current_pattern);

                        $current_url_is_ssl = preg_match('/' . $current_pattern 
. '/i',
$current_url);
                }
                else if (strcasecmp($current_ssl_action, $current_url) == 0)
                {
                        $current_url_is_ssl = true;
                }

                if ($current_url_is_ssl)
                {
                        break;
                }
        }

        if ($current_url_is_ssl && (!isset($_SERVER['HTTPS']) ||
strcasecmp($_SERVER['HTTPS'], 'on') != 0))
        {
                // Should be accessed only via SSL

                $current_url = 'https://' . $_SERVER['SERVER_NAME'] . '/' .
$current_url;

                return $this->redirect($current_url);
        }
}

This prevents people from trying to access directly to the action via
normal HTTP.

All of this is supposed to work when you have your cake HTTPDOCS and
HTTPSDOCS on the same directory.

Hope it helps :)

-MI


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Cake 
PHP" group.
To post to this group, send email to cake-php@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/cake-php
-~----------~----~----~----~------~----~------~--~---

Reply via email to