Advertisement

Google Ad Slot: content-top

Zend CSRF Protection


What is CSRF Protection?

CSRF (Cross-Site Request Forgery) is an attack where a malicious site tricks a logged-in user into submitting a request to a different site (e.g., transferring money, changing password) without their consent.


 CSRF Token Prevents:

  • Forged form submissions
  • Unwanted data modifications

Zend Framework uses a hidden CSRF token field in forms to validate that the request is legitimate.


Why Use CSRF Protection?

  • Prevents request forgery
  • Token-based verification
  • Integrated in Zend Forms

Basic Example: Zend Form with CSRF Token

1. Install laminas/laminas-session for token handle:

composer require laminas/laminas-session



2. Create Form with CSRF Field in (module\Application\src\Form\LoginForm.php)

<?php
declare(strict_types=1);
namespace Application\Form;

use Laminas\Form\Form;
use Laminas\Form\Element\Csrf;

class LoginForm extends Form
{
    public function __construct($name = null)
    {
        parent::__construct('login');

        $this->add([
            'name' => 'email',
            'type' => 'Text',
            'options' => ['label' => 'Email'],
        ]);
        // ✅ CSRF Token Field
        $this->add([
            'type' => Csrf::class,
            'name' => 'csrf',
            'options' => [
                'csrf_options' => [
                    'timeout' => 600, // Token valid for 10 minutes
                ],
            ],
        ]);

        $this->add([
            'name' => 'password',
            'type' => 'Password',
            'options' => ['label' => 'Password'],
        ]);

        $this->add([
            'name' => 'submit',
            'type' => 'Submit',
            'attributes' => [
                'value' => 'Login',
                'class' => 'btn btn-primary'
            ],
        ]);
    }
}

3. Controller Usage

use Application\Form\LoginForm;
use Laminas\View\Model\ViewModel;

public function homeAction()
{ 
    $form = new LoginForm();
    $request = $this->getRequest();
    if ($request->isPost()) {
        $form->setData($request->getPost());
        if ($form->isValid()) {
            $data = $form->getData();
            dd($data);
            // Proceed (e.g., create user)
        } else {
            // $form->getMessages() contains validation errors
        }
    }
    return new ViewModel(['form' => $form]);
}




4. View Template (module\Application\view\application\main\home.phtml)

<?= $this->form()->openTag($form) ?>
<?= $this->formRow($form->get('email')) ?>
<?= $this->formRow($form->get('csrf')) ?>  <!-- 🛡️ CSRF Token -->
<?= $this->formRow($form->get('password')) ?>
<?= $this->formSubmit($form->get('submit')) ?>
<?= $this->form()->closeTag() ?>

Behind the Scenes

  • Zend uses Laminas\Validator\Csrf
  • The CSRF token is stored in the session
  • On POST, Zend compares submitted token with session token
  • Token timeout can be configured

CSRF in Normal HTML Form (without Zend Form)

1. Add SessionManager in Module.php (module/Application/src/Module.php)

namespace Application;

use Laminas\Mvc\MvcEvent;
use Laminas\Session\SessionManager;
use Laminas\Session\Container;

class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        $sessionManager = new SessionManager();
        $sessionManager->start(); // ✅ This replaces session_start()

        // ✅ Set as default session manager for all containers
        Container::setDefaultManager($sessionManager);
    }

    public function getConfig()
    {
        return include __DIR__ . '/../config/module.config.php';
    }
}

2. Add CSRF Token Generator in Controller

use Laminas\Session\Container;

public function homeAction()
{ 
    $request = $this->getRequest();
    if ($request->isPost()) {
        $postedToken = $request->getPost('csrf');
        $container = new Container('csrf');
        // 🛡️ Validate CSRF manually
        if ($postedToken === $container->token) {
            // ✅ Valid CSRF
            $password = $request->getPost('password');
            $email = $request->getPost('email');
            // ... Save or process the data ...
            return new ViewModel(['message' => 'Form submitted successfully']);
        }else{
            // ❌ Invalid CSRF
            return new ViewModel(['error' => 'Invalid CSRF token']);
        }
    }
    // For GET: show the form
    $container = new Container('csrf');
    $token = bin2hex(random_bytes(32));
    $container->token = $token;

    return new ViewModel([
        'csrf_token' => $token,
    ]);
}

3. Use CSRF Token in Plain HTML Form (module\Application\view\application\main\home.phtml)

<?php if (isset($csrf_token)): ?>
    <form method="POST" action="">
        <label>Email: <input type="email" name="email"></label><br>
        <label>Password: <input type="password" name="password"></label><br>
        <!-- 🛡️ CSRF Token -->
        <input type="hidden" name="csrf" value="<?= $this->escapeHtmlAttr($csrf_token) ?>">
        <button type="submit">Submit</button>
    </form>
<?php elseif(isset($message)): ?>
    <h1><?= $message ?></h1>
<?php else: ?>
    <h1><?= $error ?></h1>
<?php endif; ?>   

Real-World Usage Scenarios

Use Case

Why CSRF Matters

User Registration

Prevent fake/auto form submissions

Payment Gateways

Prevent unwanted charges or redirects

Admin Panel

Block unauthorized POST/DELETE requests

API Tokens

Protect sensitive data update forms