SSL/HTTPS with Zend Framework

I spent a fair amount of time today hunting for a decent way to force Zend Framework 1.11 to use SSL. Sadly, there was no simple answer that completely worked, so after scamming pieces parts from a number of Google searches I came up with my own solution.

The task, to force all HTTP calls to HTTPS, however, I might only want to secure selected modules/controllers in the future. My solution.

In configs/application.ini I added:

ssl.modules.require_ssl = 'all';
ssl.controllers.require_ssl = '';

This could just as easily be:

ssl.modules.require_ssl = 'module1,module2,module3';
ssl.controllers.require_ssl = 'controller11';

Now create a new plugin at plugins/Ssl.php

class Plugin_Ssl extends Zend_Controller_Plugin_Abstract
    public function preDispatch($request)
        //get the config settings for SSL
        $options = new Zend_Config_Ini(APPLICATION_PATH.'/configs/application.ini');
        $secure_modules = explode(',',$options->production->ssl->modules->require_ssl); 
        $secure_controllers = explode(',',$options->production->ssl->controllers->require_ssl); 

        $front = Zend_Controller_Front::getInstance();
        $request = $front->getRequest();        
        $module = $request->getModuleName();
        $controller = $request->getControllerName();

        // Force SSL Only use it production environment
        if ( APPLICATION_ENV == 'production' )
            if ($secure_modules[0] == 'all' || in_array(strtolower($module), $secure_modules) || in_array(strtolower($controller), $secure_controllers)) {
                if (!isset($_SERVER['HTTPS']) && !$_SERVER['HTTPS']) {
                    $url        = 'https://'
                                . $_SERVER['HTTP_HOST']
                                . $request->getRequestUri();
                    $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');

Finally in your bootstrap create the following function:

    protected function _initPlugins() {
        $frontController = Zend_Controller_Front::getInstance();
        $frontController->registerPlugin( new Plugin_Ssl());        

This will execute the SSL test on every page load without having to add a call to every single controller.

That’s it. Hope it helps somebody.

Wait.. Why not just use Apache or .htaccess you ask? Because Zend’s .htaccess forces everything to index.php and the internal router gets stupid if you try and do it that way.