We’ve been making a big push lately to standard a code base for our cms. One of the things I’ve been trying to tackle was an easy way to secure urls without having to make alot of modifications to our code. Here’s a perfect example:
Let’s assume we have a Zend Module for donations in our base, that allows a non-profit organization to accept donations via Authorize.net. Obviously we want the urls for the donations module to be secure. But what if our client also wanted to accept payments for event registrations. Do we want to hardcode certain urls with https://? No. Do we want to duplicate the code we use in php to redirect the donations module to a secure url? No.
So what’s the solution? A Custom Controller Plugin and the standard application.ini file in a Zend_Framework Application that allows us to define modules, controllers, and actions to require ssl.
An Example application.ini file
modules.donations.require_ssl = true modules.events.registrations.require_ssl = true
The above example shows a snippet of our configuration file. There are three formats that we will use to enforce ssl :
modules.module_name.require_ssl = true
modules.module_name.controller_name.require_ssl = true
modules.module_name.controller_name.action_name.require_ssl = true
Now for the second part, we’ll load this Controller Plugin, that will check if any combination of module, controller and action require an ssl redirect. If we detect a redirect setting in the application.ini for any combination, we’ll rebuild the url with an https:// prefix, and redirect to that url and exit the execution stack.
Custom SSL Plugin
class Custom_Controller_Plugin_Ssl extends Zend_Controller_Plugin_Abstract {
/**
* Check the application.ini file for security settings.
* If the url requires being secured, r ebuild a secure url
* and redirect.
*
* @param Zend_Controller_Request_Abstract $request
* @return void
* @author Travis Boudreaux
*/
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$shouldSecureUrl = false;
$options = Zend_Registry::getInstance()->get('options');
if (APPLICATION_ENVIRONMENT == ENV_PRODUCTION ) {
//check configuration file for one of three require_ssl directives
//secure an entire module with modules.module_name.require_ssl = true
//secure an entire controller with modules.module_name.controller_name.require_ssl = true
//secure an action with modules.module_name.controller_name.action_name.require_ssl = true
if ($options['modules'][$request->module]['require_ssl'] ||
$options['modules'][$request->module][$request->controller]['require_ssl'] ||
$options['modules'][$request->module][$request->controller][$request->action]['require_ssl'] ){
$shouldSecureUrl = true;
}
if ($shouldSecureUrl) {
$this->_secureUrl($request);
}
}
}
/**
* Check the request to see if it is secure. If it isn't
* rebuild a secure url, redirect and exit.
*
* @param Zend_Controller_Request_Abstract $request
* @return void
* @author Travis Boudreaux
*/
protected function _secureUrl( Zend_Controller_Request_Abstract $request){
$server = $request->getServer();
$hostname = $server['HTTP_HOST'];
if (!$request->isSecure()) {
//url scheme is not secure so we rebuild url with secureScheme
$url = Zend_Controller_Request_Http::SCHEME_HTTPS . "://" . $hostname . $request->getPathInfo();
$redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
$redirector->setGoToUrl($url);
$redirector->redirectAndExit();
}
}
}
Hopefully this has been helpful. Feel free to reuse part or all of this code in your application, though we do not take any responsibilities of its use. We’d love to hear your comments and get some feedback.
Good work man. Pulling the designation for which modules, conrollers, and actions to redirect out of the front controller plugin and into the config is a nice abstraction. Simplification to configuration options feels clean and efficient.
Comment by Lance — September 22, 2009 @ 9:58 am
Hello,
I would like to use this plugin for securing login, but I don’t manage to make it work.
I have the following structure :
application
> Bootstrap.php
> config
> controllers
> IndexController.php
> plugin
> Custom_Controller_Plugin_Ssl.php
My action login is in the IndexController.
I don’t know what you called module.
I have added this line in application.ini :
index.login.require_ssl = true
And this line in the index.php (in public) to load the plugin :
$loader = new Zend_Loader_PluginLoader();
$loader->addPrefixPath(’Ssl_Helper’, ‘application/plugin/Custom_Controller_Plugin_Ssl.php’);
Could you help me make your code work?
Thank you for your time.
Neoraptor
Comment by neoraptor — December 15, 2009 @ 1:53 pm