I have developed a cakephp site that should use ssl for all pages. It works as expected except when I use redirect in a controller it redirects to http: //subdomain.domain.c
I found the error it was a misconfiguration of Apache.
Trying out Jamies solution, the site ended up in a redirect loop, because RequestHandler->isSSL() returned false even if the request was https. I then discovered that the $_SERVER['https'] was not set and the $_SERVER['port'] was 80, not 443 as expected.
At that point I have placed my ssl directives in sites-available/default,
SSLEngine on
SSLCertificateFile [path to cert file]
SSLCertificateKeyFile [path to keyfile]
Moving the ssl directives to the virtual host for the subdomain resolved the issue, with redirect loops.
Actually is also solved my initial problem because the method Router::url checks for $_SERVER['https'] if set it generates a url that starts with https: otherwise just http:
I have tested both Jameies solution and my own with rewrite rules in .htaccess and they both work as expected after the fix.
Tim
I'm taking a bit of a guess, but I suspect it is this very RewriteRule that's messing things up.
You should be "redirecting" not "rewriting". Cake's generated links are usually relative to the root, so don't specify a protocol unless you pass "true" as the second parameter.
I also have apache listening on both 80 and 443 so that I can at least respond to incorrect requests.
This is the code I have in my AppController class to do the same thing:
function beforeFilter() {
parent::beforeFilter();
$this->_setupSecurity();
}
function _setupSecurity() {
$this->Security->blackHoleCallback = '_badRequest';
if(Configure::read('forceSSL')) {
$this->Security->requireSecure('*');
}
}
/**
* The main SecurityComponent callback.
* Handles both missing SSL problems and general bad requests.
*/
function _badRequest() {
if(Configure::read('forceSSL') && !$this->RequestHandler->isSSL()) {
$this->_forceSSL();
} else {
$this->cakeError('error400');
}
exit;
}
/**
* Redirect to the same page, but with the https protocol and exit.
*/
function _forceSSL() {
$this->redirect('https://' . env('SERVER_NAME') . $this->here);
exit;
}
I also have my own config 'forceSSL' option in bootstrap.php for turning this on and off depending on the environment, so that needs to be set to true for the above to work.
Its example is already mentioned in the CookBook http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html#usage
class AppController extends Controller {
// Add security component
public $components = array('Security');
public function beforeFilter() {
$this->Security->blackHoleCallback = 'forceSSL';
$this->Security->requireSecure();
}
// Add this function in your AppController
public function forceSSL() {
return $this->redirect('https://' . env('SERVER_NAME') . $this->here);
}
}