Authentication with Zend Framework

Sonntag, 18.09.2011 | PHP | Keine Kommentare | php , zend framework

In this example I will show how to implement an authentication logic in Zend Framework with Zend_Auth. What we have is a module based MVC with two modules.

  • default - default module
  • restricted - restricted area (which needs authentication)

First of all we need a login action in our default module index controller for users to enter there credentails. In this example we authenticate against a Database Table where credentails are stored. There are more adapters available.

  • Database Table Authentication
  • Digest Authentication
  • HTTP Authentication Adapter
  • LDAP Authentication
  • Open ID Authentication
/* 
 * application/controllers/IndexController.php
 */
class IndexController extends Zend_Controller_Action
{
	public function loginAction()
    {
    	if($this->getRequest()->isPost()) {
    		$username = $this->_getParam('username', null);
    		$password = $this->_getParam('password', null);
    		
    		if(!is_null($username) && !is_null($password)) {
    			$dbAdapter = Zend_Registry::get('dbAdapter');
    			$authAdapter = new Zend_Auth_Adapter_DbTable(
				    $dbAdapter,
				    'users',     // Table name
				    'username',  // Idenitity column
				    'password'   // Password column
				);
				$authAdapter->setIdentity($username)->setCredential(md5($password));
				
				$auth = Zend_Auth::getInstance();
				$result = $auth->authenticate($authAdapter);
				
				if ($result->isValid()) {
					// Print the result row
					//print_r($authAdapter->getResultRowObject());
					$this->_forward('index', 'index', 'restricted');
					return;
				} else {
					echo 'invalid username/password';
				}
    		} else {
    			echo 'username/password is empty';
    		}
    	}
    }
}

Anyway if result is valid we can forward user to the restricted area (line 28).

Now we have to check if user is logged in. As we need to do this on every page it is a good idea to use a plugin. So let's create an authentication plugin.

/* 
 * library/My/Plugin/Auth.php
 */
class My_Plugin_Auth extends Zend_Controller_Plugin_Abstract 
{
	public function preDispatch()
	{
		$module = $this->getRequest()->getModuleName();
		if($module == 'restricted') {
			$auth = Zend_Auth::getInstance();
			if(!$auth->hasIdentity()) {
			 	$this->getRequest()->setModuleName('default');
			 	$this->getRequest()->setControllerName('index');
			 	$this->getRequest()->setActionName('login');
			}
		}
	}
}

If user has no identity and tries to view a page in the restricted area he will be redirected to the login page. To register this plugin we need to add the following line to our application.ini.

resources.frontController.plugins.one = "My_Plugin_Auth"

As Zend_Auth is implemented as singleton you can access it from everywhere. You can check if user has identity with following method:

Zend_Auth::getInstance()->hasIdentity()


Minimal Ubuntu with Fluxbox

Freitag, 22.04.2011 | Linux | 4 Kommentare | gnome 3 , unity , fluxbox , ubuntu

Ubuntu is going to use Unity instead of Gnome 3 as default window manager. For me both needs getting used to. So I've been looking for alternative desktop environments and window managers.

Ultimately I decided to use a minimal Ubuntu installation with Fluxbox as window manager. As Fluxbox is very fast and only needed packages are installed the whole System feels quick.

And this how it looks like:

fluxbox

If you are bored of Unitiy and Gnome, too. Install minimal Ubuntu and following packages

sudo apt-get install xorg fluxbox slim xfe chromium-browser

and you are done!


How to use cURL through a Proxy Server in PHP

Donnerstag, 31.03.2011 | PHP | Keine Kommentare | php , proxy server , curl

Many companies allow access to the Internet through a Proxy Server, only. That makes it hard to developers to download files with standard features. One way is to use cURL. It's possible to setup cURL to use a Proxy Server.

In PHP it looks like this:

$res = curl_init();  
curl_setopt($res, CURLOPT_URL, 'http://www.someurl.com/');  
curl_setopt($res, CURLOPT_RETURNTRANSFER, 1);  
curl_setopt($res, CURLOPT_PROXY, '192.168.10.1:8080');  
curl_setopt($res, CURLOPT_PROXYUSERPWD,'user:pass');  
$string = curl_exec($res);  
curl_close($res); 

Zend Framework without mod_rewrite

Samstag, 05.02.2011 | PHP | 1 Kommentar | mod_rewrite , zend framework , php

For my hosting package, Apache mod_rewrite isn't enabled. As you can imagine it's not funny to use Zend Framework without it. With a little bit of coding it's possible to use the framework, anyway.

The first thing that we need is a own route. Rob Allen has created a route for URLs without mod_rewrite. This is a modified version of it

class My_Controller_Router_Route_RequestVars implements Zend_Controller_Router_Route_Interface
{
 protected $_current = array();

    /**
     * Instantiates route based on passed Zend_Config structure
     */
    public static function getInstance(Zend_Config $config)
    {
        return new self();
    }

    /**
     * Matches a user submitted path with a previously defined route.
     * Assigns and returns an array of defaults on a successful match.
     *
     * @param string Path used to match against this routing map
     * @return array|false An array of assigned values or a false on a mismatch
     */
    public function match($path)
    {
        $frontController = Zend_Controller_Front::getInstance();
        $request = $frontController->getRequest();
        /* @var $request Zend_Controller_Request_Http */
        
        $baseUrl = $request->getBaseUrl();
        if (strpos($baseUrl, 'index.php') !== false) {
            $url = str_replace('index.php', '', $baseUrl);
            $request->setBaseUrl($url);
        }
        
        $params = $request->getParams();
        
        if (array_key_exists('module', $params)
                || array_key_exists('controller', $params)
                || array_key_exists('action', $params)) {
            
            $module = $request->getParam('module', $frontController->getDefaultModule());
            $controller = $request->getParam('controller', $frontController->getDefaultControllerName());
            $action = $request->getParam('action', $frontController->getDefaultAction());

            $result = array('module' => $module, 
                'controller' => $controller, 
                'action' => $action, 
                );
            $this->_current = $result;
            return $result;
        }
        return false;
    }

    /**
     * Assembles a URL path defined by this route
     *
     * @param array An array of variable and value pairs used as parameters
     * @return string Route path with user submitted parameters
     */
    public function assemble($data = array(), $reset=false, $encode = false)
    {
        $frontController = Zend_Controller_Front::getInstance();
        
        if(!array_key_exists('module', $data) && !$reset 
            && array_key_exists('module', $this->_current)
            && $this->_current['module'] != $frontController->getDefaultModule()) {
            $data = array_merge(array('module'=>$this->_current['module']), $data);
        }
        if(!array_key_exists('controller', $data) && !$reset 
            && array_key_exists('controller', $this->_current) 
            && $this->_current['controller'] != $frontController->getDefaultControllerName()) {
            $data = array_merge(array('controller'=>$this->_current['controller']), $data);
        }
        if(!array_key_exists('action', $data) && !$reset 
            && array_key_exists('action', $this->_current)
            && $this->_current['action'] != $frontController->getDefaultAction()) {
            $data = array_merge(array('action'=>$this->_current['action']), $data);
        }
        
        $url = '';
        if(!empty($data)) {
            $url = '?' . http_build_query($data, '', '&');
        }

        return $url;
    }
}

To add this route, we need to tell the router about it in our index.php like this:

$bootstrap->bootstrap('frontController');
$front = $bootstrap->frontController;
$router = $front->getRouter();
$router->addRoute('requestVars', new My_Controller_Router_Route_RequestVars());

Second thing we need is a URL view helper that is used instead of Zend Frameworks URL view helper.

/**
 * URL view helper
 * 
 * @category   My
 * @package    My_View
 * @subpackage Helper
 * @author Burak Yueksel
 * @copyright Copyright (c) 2010 Burak Yueksel
 *
 */
class My_View_Helper_Url extends Zend_View_Helper_Abstract
{
	public function url(array $urlOptions = array(), $numericPrefix='', $argSeparator='&')
	{
		$request = Zend_Controller_Front::getInstance()->getRequest();
		
		if(!isset($urlOptions['module'])) $urlOptions['module'] = $request->getModuleName();
		if(!isset($urlOptions['controller'])) $urlOptions['controller'] = $request->getControllerName();
		if(!isset($urlOptions['action'])) $urlOptions['action'] = $request->getActionName();
		 
		$hyperLink = '/?module='.$urlOptions['module'].$argSeparator;
		$hyperLink .= 'controller='.$urlOptions['controller'].$argSeparator;
		$hyperLink .= 'action='.$urlOptions['action'].$argSeparator;
		
		unset(
			$urlOptions['module'], 
			$urlOptions['controller'], 
			$urlOptions['action']
		);
		
		if(sizeof($urlOptions)) {
			$hyperLink .= http_build_query($urlOptions, $numericPrefix, $argSeparator);	
		}
		return $hyperLink;
	}
}

This view helper will create URLs like this

/?module=index&controller=index&action=whatever&param1=hello&param2=world

This also works with Zends URL view helper but only if you reqeust the website with /?controller=index.

Now we need to add configuration for our own view helper to application.ini

resources.view.helperPath.My_View_Helper = APPLICATION_PATH "/../library/My/View/Helper"

Thats it! Now we're able to build websites using Zend Framework without mod_rewrite.