🔐 Sistema de tokens CSRF — prevencion de ataques
Actualizado: 2024-12-01
PrestaShop usa tokens para prevenir ataques CSRF (Cross-Site Request Forgery). Cualquier formulario o peticion AJAX que realice una accion con efectos secundarios debe incluir y verificar un token.
#Tipos de token en PrestaShop
| Tipo | Funcion | Duracion | Uso |
|---|---|---|---|
| Token estatico del FO | Tools::getToken(false) | Sesion del cliente | Formularios y AJAX en FO |
| Token de pagina del FO | Tools::getToken(true) | Unico por pagina | Formularios de una sola accion |
| Token del BO | Tools::getAdminToken(...) | Sesion del empleado | Acciones en el Back Office |
| Token de confirmacion | Tools::encrypt($data) | Unico por datos | Links de email, confirmaciones |
#Token estatico del Front Office
Generar y verificar token en FO
php
<?php
// ── En el FrontController — generar y asignar ──
public function initContent(): void
{
parent::initContent();
// Token estatico — igual para toda la sesion del cliente
$staticToken = Tools::getToken(false);
$this->context->smarty->assign([
'static_token' => $staticToken,
'my_form_data' => $this->getFormData(),
]);
}
// ── En el metodo de procesado del formulario ──
public function postProcess(): void
{
if (!Tools::isSubmit('submitMyForm')) {
return;
}
// Verificar el token
$token = Tools::getValue('token');
if (!$token || $token !== Tools::getToken(false)) {
$this->errors[] = $this->trans(
'Invalid token.',
[],
'Shop.Notifications.Error'
);
return;
}
// Procesar el formulario...
}
Incluir token en templates Smarty (FO)
smarty
{* En el template del formulario *}
<form method="post" action="{$urls.pages.my_page}">
{* Campo oculto con el token *}
<input type="hidden" name="token" value="{$static_token}">
<input type="hidden" name="submitMyForm" value="1">
<div class="form-group">
<label for="name">Nombre</label>
<input type="text" id="name" name="name" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Enviar</button>
</form>
#Token del Back Office
Tokens en el Back Office
php
<?php
// ── Token del AdminController actual ──
$token = Tools::getAdminToken(
'AdminMyController' // Nombre del controller
. (int) Tab::getIdFromClassName('AdminMyController') // ID del tab
. (int) Context::getContext()->employee->id // ID del empleado
);
// ── Token simplificado (PS 1.7+) ──
$token = Tools::getAdminTokenLite('AdminMyController');
// ── Verificar el token en el controller ──
if (!Tools::isTokenValid()) {
// Token invalido o expirado
die('Token invalido');
}
// ── Usar en URLs del BO ──
$url = $this->context->link->getAdminLink('AdminMyController') . '&action=myAction';
// getAdminLink ya incluye el token automaticamente
// ── En el template del BO (Smarty) ──
// {$token} esta disponible automaticamente en todos los templates del BO
// <input type="hidden" name="token" value="{$token}">
#Tokens en peticiones AJAX
Enviar y verificar tokens en peticiones AJAX
javascript
// ── FO: Token en fetch() ──
// El token debe estar disponible como variable JS
// En el FrontController:
// Media::addJsDef(['mymodule' => ['token' => Tools::getToken(false)]]);
const response = await fetch('/module/mymodule/ajax', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
action: 'myAction',
token: mymodule.token, // Token desde variable JS
data: JSON.stringify({ key: 'value' }),
}),
});
// ── FO: jQuery AJAX con token ──
$.ajax({
url: mymodule.ajax_url,
type: 'POST',
data: {
action: 'myAction',
token: mymodule.token,
id: productId,
},
success: function(response) { /* ... */ },
});
// ── BO: Token en AJAX (el BO lo tiene en window.token) ──
fetch(window.location.pathname, {
method: 'POST',
body: new URLSearchParams({
ajax: 1,
action: 'myAction',
token: window.token, // Token del BO
}),
});
#Verificar tokens en formularios
Verificacion robusta de token en ModuleFrontController
php
<?php
public function postProcess(): void
{
// ── Patron completo de verificacion ──
// 1. Verificar que es un submit del formulario
if (!Tools::isSubmit('submitMyAction')) {
return;
}
// 2. Verificar token CSRF
if (!Tools::isTokenValid('mymodule')) {
// PS 1.7+ tiene isTokenValid para tokens especificos
$this->errors[] = 'Token invalido';
return;
}
// Alternativa para PS 1.6+:
// $token = Tools::getValue('token');
// if ($token !== Tools::getToken(false)) { ... }
// 3. Verificar autenticacion si es necesario
if (!$this->context->customer->isLogged()) {
Tools::redirect($this->context->link->getPageLink('my-account'));
return;
}
// 4. Procesar la accion (ya verificada)
$this->processMyAction();
}
Descargar en Markdown
Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.