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:
link('Login', '/account/login', array('class' =>
'login')); ?>
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;