Posts Tagged ‘zend’

MVC in ZF2

16/02/2013

ZF2 file structure

config
  autoload
  application.config.app 

data
  cache

module
  Application
   Module.php 
   config
      module.config.pgp
    src
      Application
        Controller
          IndexController.php
     view
       application
         index
           index.phtml 
        error
        layout 

public
  images
  js
  css
  .htaccess
  index.php 

vendor
  zendframework

application.config.app 

array(
  ‘modules’ =>array( //list of modules you want to use
    ‘Application’
  ) ,
  ‘module_listener_options’ =>array( //modules options as autoloading and paths
    ‘config_glob_paths’ => array(
      ‘config/autoload/{,*.}{global,local}.php’,
    ),
    ‘module_paths’=>array(
      ‘./module’,
      ‘./vendor’,
    )
  );
); 

ZendServiceManager

ServiceManager is a Service Locator where you register services and later retrive them by configuration.

Types of services: explicit services, invokables to instatiate, factory returing object, aliases, unknown services, scoped containers, shared or not.

module/Application/Module.php

namespace Application;

use ZendMvcModuleRouteListener;
use ZendMvcMvcEvent;

class Module
{
  public function getConfig(){
    return include __DIR__ . ‘/config/module.config.php’;
  }

module/Application/config/module.config.php 

return array(
  ‘router’=>array(
    ‘routes’=>array(
      ‘home=>array(
        ‘type’=>’ZendMvcRouterHttpLiteral’, //You can use Segment type
        ‘options’=>array(
          ‘route’=>’/’,
          ‘defaults’=>array(
            ‘controller’=>’ApplicationControllerIndex’,
            ‘action’=>’index’,
          ),
        ),
      ),
    ),
  ),
  ‘controllers’=>array(
    ‘invocables’=>array(
      ‘ApplicationControllerIndex’=>’ApplicationControllerIndexController’
    )
  ),
  ‘view_manaer’=>array(
   ‘display_not_found_reason’=>true,
   ‘display_exceptions’=>true,
    ‘doctype’=>’HTML5’,
    ‘not_found_template’=>’error/404’,
    ‘exception_template’=>’error/index’,
    ‘template_map’=>array(
      ‘layout/layout’=>__DIR__.’/../view/layout/layout.phtml’,
      ‘application/index/index’=>__DIR__.’/../view/application/index/index.phtml’,
      ‘error/404’=>__DIR__.’/../view/error/404.phtml’,
      ‘error/index’=>__DIR__.’/../view/error/index.phtml’,
    ),
    ‘template_stack_path’=>array(
      __DIR__.’/../view’,
    ),
  ),
/* … */
); 

module/Application/src/Application/Controller/IndexController.php

namespace ApplicationController;

use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;

class IndexController extends AbstractActionController
{
  public function indexAction(){
    return ViewModel();
  }

The ViewModel will return view/application/index/index.phtml contents.

Source Zend webinar.

Get started to zf2 and why to switch from zf1

15/02/2013
  • ZF1 way: Singletons, registers, soft and hard dependencies
  • ZF2 way: Even-Driven Services flexibility, better secure defaults, contexts of escaping, dependencies injection (inversion of control).

Instead of using hard dependencies and dificult to test code:

public function someAction(){  $front = Zend_Controller_Front::getInstance();  $bootstrap = $front->getParam('bootstrap');  $db = $bootstrap->getResource('db');  $service = new SomeService($db);  $this->view->results = $service->doSomething();}

 

With ZF2 you can achieve this:

public function setService($service){  $this->service = $service;}public function someAction(){  return array(    'results' => $this->service->doSomething();  ); }

You need to use Dependency Injection when getting the controller:

function ($controllers){  $services = $controllers->getServiceLocator();  $service = $services->get('SomeService');  $controller = new SomeController();  $controller->setService($service);  return $controller;}

Benefits:

  • Easy replacements which means easier to test
  • Code for construcion is located in one place, easy reviewed place.
  • You can do things for separate services more easily

 

Zend/ServiceManager

No discovery, you code injections. Explicit writing means less debuging

//Explicit services
array(‘services’, array(
  ‘foo’=>new SomeComponentFoo,
  ‘bar’=>$someObjectInstance,
));
//Instantiable class
array(‘invokables’, array(
  ‘foo’=>’SomeComponentFoo’,
));
//Callable that returns and object
array(‘factories’, array(
  ‘foo’=>function($services){
    return new SomeComponentFoo(
      $services->get(‘bar’)
    )
  },
  ‘bar’=>’SomeStatic::method’,
  ‘baz’=>’SomeClassImplementingFactoryInterface’,
  ‘bat’=>’SomeFunctionClass’,
));
//Callable that handles multiple services
array(‘abstract_factories’, array(
  ‘
SomeClassImplementingFactoryInterface‘,
  $
someAbstractFactoryInstance
));
//Example of abstract factory
class SampleAbstractFactory implements AbstractFactoryInterface {
  public funtion canCreateServiceWithName(
   ServiceLocatorInterface $services, $name, $requestedName
  ) { /* code.. */ }
  public funtion createServiceWithName  /* code.. */

//(un)Share a service
array(‘shared’, array(
  ‘EventManager’=>false, //default is true
));
 
//Operations on new instances, for example to automate injections like this
array(‘initializers’, array(
  function($instance, $services) {
    if($instance instanceof EventManagerAwareInterface) {
      $instance->setEventManager(
        $services->get(‘EventManager’)
      )
    }
  }
));
//Plugin example. $heplers is view helper plugin manager instance
array(‘factories’, array(
  ‘something’=> function($helpers) {
    $services = $helpers->getServiceLocator();
    $model = $services->get(‘SomeModel’);
    $helper = new SomethingHelper($model);
    return $helper;
  }
));

Event Manager

Listen and react to trigger events in simple way

$events = new EventManager();
$events->attach(‘do’, function($e){
  $event = $e->getName();
  $params= $e->getParams();
  printf(‘Handled event %s with parameters %s, 
  $event, json_enccode($params));
});
$params=array(‘foo’ => ‘bar’, ‘baz’ => ‘bat’);
$events->trigger(‘do, null, $params);
 

Listen and react to trigger events to a group of objects or objects that don’t exist yet.

$shared = $events->getSharedEventManager();
$shared =  $services->get(‘SharedEventManager’);

$shared->attach(‘ZendStdlibDispatchableInterface’, ‘dispatch’, $callback, $priority);

Everything is an event

Boostrap listeners run modules, route listeners run modules, dispatch listeners run modules.

Controllers are services

Use ServiceManager to wire default workflow and event listeners.

Plug and play modules

They should do one thing and do it well. They provide services for MVC and wire event listeners.

 Modules are implemented as a namespace with a single Module.php class file.

 

 

Module example

Edit module/MyMarkdown/Module.php

namespace  MyMarkdown;

use ZendViewHelperAbstractHelper;

class Module extends AbstractHelper
{
  public function getViewHelperConfig(){
    return array(‘services’, array(‘markdown’ => $this));
  }
  public function __invoke($string = null){
    require_once ‘php-markdown/markdown.php’;
    return Markdown($string);
  }
}

Add the MyMarkdown module to application in config/application.config.php

return array(
  ‘modules’ => array(
    ‘Application’,
    ‘MyMarkdown’,
  ),
  /* … */
); 

Test it in view script

<?= $this->markdown($this->someMarkdowntext) ?> 

What you can do if the module you want exist? Use ‘git submodule add’, add module name to your config/application.config.php file and you are done.

 

Controller example

They are very similar than in ZF1. In ZF2 you return something.

namespace ApplicationController;

use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;

class IndexController extends AbstractActionController
{
  public function indexAction()
  {
    return new ViewModel();
  }

 

Key points to remember for using ZF2

  • Know to configure services.
  • Know to wire event listeners.
  • Controllers return informa
    tion as they are now services.
  • Modules inform the MVC of services (controllers!) and wire events.

 

Secure Zend Framework programing in ZF2

15/02/2013

Comments on this webinar:

What are the most common security risks?

OWASP Top 10 Application Security Risks – 2010

A1-Injection Injection flaws, such as SQL, OS, and LDAP injection, occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing unauthorized data.
A2-Cross Site Scripting (XSS) XSS flaws occur whenever an application takes untrusted data and sends it to a web browser without proper validation and escaping. XSS allows attackers to execute scripts in the victim’s browser which can hijack user sessions, deface web sites, or redirect the user to malicious sites.
A3-Broken Authentication and Session Management Application functions related to authentication and session management are often not implemented correctly, allowing attackers to compromise passwords, keys, session tokens, or exploit other implementation flaws to assume other users’ identities.
A4-Insecure Direct Object References A direct object reference occurs when a developer exposes a reference to an internal implementation object, such as a file, directory, or database key. Without an access control check or other protection, attackers can manipulate these references to access unauthorized data.
A5-Cross Site Request Forgery (CSRF) A CSRF attack forces a logged-on victim’s browser to send a forged HTTP request, including the victim’s session cookie and any other automatically included authentication information, to a vulnerable web application. This allows the attacker to force the victim’s browser to generate requests the vulnerable application thinks are legitimate requests from the victim.
A6-Security Misconfiguration Good security requires having a secure configuration defined and deployed for the application, frameworks, application server, web server, database server, and platform. All these settings should be defined, implemented, and maintained as many are not shipped with secure defaults. This includes keeping all software up to date, including all code libraries used by the application.
A7-Insecure Cryptographic Storage Many web applications do not properly protect sensitive data, such as credit cards, SSNs, and authentication credentials, with appropriate encryption or hashing. Attackers may steal or modify such weakly protected data to conduct identity theft, credit card fraud, or other crimes.
A8-Failure to Restrict URL Access Many web applications check URL access rights before rendering protected links and buttons. However, applications need to perform similar access control checks each time these pages are accessed, or attackers will be able to forge URLs to access these hidden pages anyway.
A9-Insufficient Transport Layer Protection Applications frequently fail to authenticate, encrypt, and protect the confidentiality and integrity of sensitive network traffic. When they do, they sometimes support weak algorithms, use expired or invalid certificates, or do not use them correctly.
A10-Unvalidated Redirects and Forwards Web applications frequently redirect and forward users to other pages and websites, and use untrusted data to determine the destination pages. Without proper validation, attackers can redirect victims to phishing or malware sites, or use forwards to access unauthorized pages.

 

“Filter input, escape output”
Yest, but it’s not enough.

Security tools in ZF2

  • ZendAuthentication
  • ZendPermissions
  • ZendFilter
  • ZendValidator
  • ZendInputFilter
  • ZendEscaper
  • ZendCaptcha
  • ZendCrypt
  • ZendMath

 

    ZendAuthentication

    API for authentication and includes concrete authentication adapters for common use case scenarios:

    • Database table
    • Digest
    • HTTP
    • LDAP
    • Or your custom authentication adapter…

    Example of ZendAuthentication use:

      use ZendAuthenticationAuthenticationService;$auth = new AuthenticationService();$authAdapter = new MyAuthAdapter($username, $password);if(!$result->isValid()){//auth failedvar_dump($result->getMessages());}else{//auth success, $username is stored in the session}

      ZendPermissions

      Proviedes access control list (ACL) for privileges management

      • Resource: An object which access is controlled
      • Role: An object that may request access to a resource.

      Example of ZendPermissions use:

      use ZendPermissionsAclAcl;use ZendPermissionsAclRoleGenericRole as Role;use ZendPermissionsAclResourceGenericResource as Resource;$acl = new Acl();$acl->addRole(new Role('guest'));    ->addRole(new Role('member'));    ->addRole(new Role('admin'));$parents = array('guest', 'member', 'admin');$acl->addRole(new('someUser'), $parents);$acl->addResource(new Resource('someResource'));$acl->deny('guest', 'someResource');$acl->deny('member', 'someResource');echo $acl->isAllowed('someUser', 'someResource')? 'allowed' : 'denied';

      ZendPermissionsRbac adapter in ZF2.1 is a new Role-Based Access Control based in PHP 5.3 SPL RecursiveIterator. It put emphasis on roles and their permissions rather than resource objects:

      • identity: one or more roles
      • role: requests acces to a permission
      • permission is givet to a role.

       

      ZendFilter

      Provides a set of commonly needed data filters and a chainging mechanism by which multiple filters may be applied.

      Standard Filter Classes…

      • Alnum
      • Alpha
      • BaseName
      • Boolean
      • Compress/Decompress
      • Digits
      • Dir
      • Encrypt/Decrypt
      • HtmlEntities
      • Int
      • Null
      • NumberFormat
      • PregReplace
      • RealPath
      • StringToLower/ToUpper
      • StringTrim
      • StripNewLines/Tags
      • Callback (custom filter)

       

      ZendValidator

      Provides a set of commonly needed validators and a validator chainging mechanism by which multiple validators may be applied.

      It examines its input with respecto to requirements and
      productes a boolean result whether the input successfully validates against the requirements.

      $validator = new ZendValidatorEmailAddress;
      if(!$validator->isValid($email)){//valid email}else{//print reasons email is invalidvar_dump($validator->getMessages());}

       

      Standard Validator Classes…

      • Alnum
      • Alpha
      • Barcode
      • Between
      • CreditCard
      • Date
      • DbRecordExists and NoRecordExists
      • Digits
      • EmailAddress
      • GreaterThan/LessThan
      • Hex
      • Hostname
      • Iban
      • Identical
      • InArray
      • Ip
      • Isbn
      • NotEmpty
      • PostCode
      • Regex
      • Sitemap
      • Step
      • StringLength
      • Callback (custom filter)

       

      ZendInputFilter

      Can be used to filter and validate generic sets of input data. For instance $_GET, $_POST, CLI, etc

      use ZendInputFilterInputFilter;use ZendInputFilterInput;use ZendValidator;$email = new Input('email');$email->getValidatorChain()  ->addValidator(new ValidatorEmailAddress());$password = new Input('password');$password ->getValidatorChain()  ->addValidator(new ValidatorStringLength(8));$inputFilter = new InputFilter();$inputFilter->add($email)            ->add($password)            ->setData($_POST);if(!$inputFilter->isValid()){//form is valid}else{//print reasons form is invalidvar_dump($inputFilter->getInvalidInput());}

       

       

      ZendEscaper

      Always escape the output, multiple formats:

      • escapeHtml()
      • escapeHtmlAttr()
      • escapeJs()
      • escapeUrl()
      • EscapeCss()

      ZendCaptcha

      Prevent submision from automated tools (Figlet, AbstractWord, Dumb, Image, ReCaptcha)

      $captcha = new ZendCaptchaFiglet(array( 'name=>'foo', 'wordLen'=>6, 'timeout'=>300,));$id = $captcha->generate();echo $captcha->getFiglet()->render($captcha->getWord());//On subsequent requestif($captcha->isValid($_POST['foo'], $_POST)){  //validated}

       

      ZendCrypt

      Use cryptography in a convenient way (instead of php built-in functions and extensions crypt, mcrypt, openssl, hash, mhash):

      • ZendCryptPassword
      • ZendCryptKeyDerivation
      • ZendCryptSymmetric
      • ZendCryptPublicKey
      • ZendCryptHash
      • ZendCryptHmac
      • ZendCryptBlockCipher

      Example of how to encrypt sensitive data:

      • ZendCryptBlockCipher symmetric encryption and authenication (HMAC)
      • Simplified API: setKey($key), encrypt($data), decrupt($data) uses Mcrypt adapter (Zend CryptSymmetricMcrypy) for us.
      • Defult values used by BlockCipher:
        • AES (256 bits key)
        • CBC mode + HMAC (SHA-256)
        • PKCS6 padding mode (RFC 5652)
        • PBKDF2 to generate encryption key + auth key for HMAC
        • Random IV for each encryption

      BlockCipher using AES encryption

      use ZendCryptBlockCipher;$cipher = BlockCipher::factory(  'mcrypt',   array('algorithm' => 'aes'));$cipher->setKey('this is the encryption key');$plaintext = 'This is the sensitive message to encrypt';//encoded base64, get binary using setBinaryOutput(true)$encrypted = $cipher->encrypt($plaintext);// You will see three parts: HMAC, IV and ciphertextprintf("encrypted text: %sn", $encrypted); file_put_contents('test.crypt',  $encrypted);

       

      BlockCipher decryption

      use ZendCryptBlockCipher;$cipher = BlockCipher::factory(  'mcrypt',   array('algorithm' => 'aes'));$cipher->setKey('this is the encryption key');$encrypted = file_get_contents('test.crypt');$plaintext = $cipher->decrypt($encrypted );printf("Dencrypted text: %sn", $plaintext );

       

      Example of how to store a password:

      Insecure, old school: MD5 password or/and salt random string (In a 4 core CPU you can break md5 8 char passwords in less than 2 hours)

      New way: bcrypt (Blowfish cipher is secure way now)

      bcrypt is secure because is very slow and attacks need huge amount of time to be completed (cost value determine how expensive is bcrypt, by default 14 that is equivalent to 1 second of computation using Core i5 CPU at 3.3Ghz.. Check taht your system use at least 1 second)

      Example of how to encrypt the password with bcrypt:

      use ZendCryptPasswordBcrypt;$bcrypt = new Bcrypt();$start = microtime(true);$hash =$bcrypt->create('password');$end = microtime(true);printf("Hash      : %s, %hash); //string of 60 bytesprintf("Exec. time: %.2fn", $end-$start);

       

      To check if password the user is valid, you verify them using the hash:

      $is_valid = bcrypt::verify($password, $hash)

       

      ZendMath

      PHP generate pseudo-random values but they are not good for cryptography purposes.

      You can get secure random numbers in PHP if you have openssl PHP extension:

      openssl_random_pseudo_bytes()

      Zend use most secure available function at the moment, never PHP primitives if $strong=true.

      ZendMathMath:randBytes($lenggth, $strong=false)

      ZendMathMath:rand($min, $max, $strong=false)