How to work with CSRF token in Phalcon (Per Session) [A Good Solution]


Nov '15

Mar '16

2

1257

0

I worked with phalcon and it's amazing. I use ajax for all of my requests. After many updates I had problem with Phalon's built-in CSRF library. I read many topics in phalcon's forum and stackoverflow. None of them helped me much.

As many of you know, if you use Phalcons methods for handling CSRF, there will be a prblem with mutiple windows/tabs.

So I made a solution myself and of course I tried "per session" method. And I also used Phalcon's built-in CSRF library to make token for a session.

I wrote this library:

<?php
namespace Your\Namespace\Library;
/**
 * Class TokenManager
 *
 * @package Your\Namespace\Library
 */
class TokenManager extends \Phalcon\Mvc\User\Component
{
    /**
     * Generates token per session
     */
    public function generateToken($type)
    {
        $this->session->set('sessionToken' . $type, [
            'tokenKey' => $this->security->getTokenKey(),
            'tokenValue' => $this->security->getToken()
        ]);
    }
    /**
     * Checks token given values against session values
     *
     * @param $tokenKey
     * @param $tokenValue
     * @return bool
     */
    public function checkToken($type, $tokenKey, $tokenValue)
    {
        if ($this->session->has('sessionToken' . $type)) {
            $token = $this->session->get('sessionToken' . $type);
            if ($token['tokenKey'] == $tokenKey && $token['tokenValue'] == $tokenValue) {
                return true;
            }
            return false;
        }
        return false;
    }
    /**
     * Checks if user have token or not
     *
     * @return bool
     */
    public function doesUserHaveToken($type)
    {
        if ($this->session->has('sessionToken' . $type)) {
            return true;
        }
        return false;
    }
    /**
     * Gets token values from session
     *
     * @return array|bool
     */
    public function getToken($type)
    {
        if ($this->session->has('sessionToken' . $type)) {
            $token = $this->session->get('sessionToken' . $type);
            return [
                'tokenKey' => $token['tokenKey'],
                'tokenValue' => $token['tokenValue']
            ];
        }
        return false;
    }
}
?>

In controller file I wrote this:

<?php

namespace Your\Namespace\Contollers;

use Your\Namespace\Library\TokenManager;

class SomeController extends \Phalcon\Mvc\Controller
{
    public $tokenManager;

    public function initialize()
    {
        $this->tokenManager = new TokenManager();
        if (!$this->tokenManager->doesUserHaveToken('User')) {
            $this->tokenManager->generateToken('User');
        }

        // 
        $this->view->token = $this->tokenManager->getToken('User');
    }

    public function ajaxAction()
    {
        if (!$this->request->isPost() || !$this->request->isAjax()) {
            $this->response->redirect();
            return;
        }

        if (!$this->tokenManager->checkToken('User', $this->request->getPost('tokenKey'), $this->request->getPost('tokenValue'))) {
            // Json Output
            return;
        }
    }
}

For html part:

...
<body>
    ...
    <input type="hidden" id="token" name="{{ token['tokenKey'] }}" value="{{ token['tokenValue'] }}">
</body>
</html>

For js (I use jQuery) and ajax:

$.ajax({
        type: 'post',
        url: 'path/to/ajax',
        dataType: 'json',
        data: {
            tokenKey: $('#token').attr('name'),
            tokenValue: $('#token').attr('value'),
            otherData: 'blah blah blah'
        }
    });
    ...

Hope its helpfull.


Thien
13.1k
edited Nov '15
Nov '15

Thanks you share tips :)

Thanks you my Countryman :) خوشحالم که یک ایرانی رو اینجا میبینم. واقعاً هیچ منبع فارسی ای برای فالکون موجود نیست! هیچکس انگار با فالکون کار نمیکنه به جز من و شما:)