← News
/PLAYBOOK · 2026-08-04

Practical CSRF Defense: Token and Nginx Dual Protection

This tutorial explains CSRF (cross-site request forgery) and a three-layer defense: application synchronizer tokens, SameSite cookies, and Nginx Referer checks. It includes PHP code and verification steps for Web developers and ops/security engineers.

Scope

CSRF defense applies to all cookie-session Web apps, including admin backends, payment callbacks, profile updates, and other high-risk operations. If the app relies only on cookie auth with no CSRF controls, an attacker can induce a logged-in user to send malicious requests—password change, privilege abuse, or data tampering. This tutorial applies to mainstream stacks (PHP/Java/Python) and Nginx reverse-proxy environments.

Prerequisites

Mechanism

CSRF abuses the browser automatically attaching cookies: when a user visits a malicious page, a form or image request carries the target site's session cookie, and the server cannot tell whether the user initiated the request. Defense means the server can verify the request origin. Common controls: synchronizer tokens, SameSite cookies, Referer checks. Synchronizer tokens are the preferred approach—they do not depend on browser behavior and have the best compatibility.

Procedure

Step 1: Add CSRF Token at the application layer

Embed a random token in the form and store it in Session. On submit, compare with hash_equals (constant-time):

<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) {
        http_response_code(403);
        exit('CSRF validation failed');
    }
}
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
?>

Output a hidden field in the form: <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">

Step 2: Set SameSite Cookie

setcookie('session_id', $sid, [
    'httponly' => true,
    'samesite' => 'Lax',
    'secure'   => true
]);

SameSite=Lax blocks cookies on cross-site requests. Secure forces HTTPS. HttpOnly prevents XSS cookie theft.

Step 3: Nginx Referer check (defense in depth)

location ~ ^/(admin|api)/ {
    if ($http_referer !~ "^https?://(www\\.)?example\\.com/") {
        return 403;
    }
    proxy_pass http://127.0.0.1:8080;
}

Note: Referer checks alone are not enough (empty Referer or same-origin XSS can bypass). Use them with tokens.

Step 4: Secondary verification for sensitive operations

For password changes, deletes, and other sensitive actions, add a second confirmation (CAPTCHA or re-enter password) to shrink the attack surface.

Verification

FAQ

Q1: Does token validation affect every POST?

Only endpoints that enable it. Apply it to all authenticated writes. GET needs no check but must not mutate state.

Q2: How do SPA + API setups prevent CSRF?

Put the token in the Authorization header (not a cookie) and CSRF does not apply. If cookies are required, use SameSite=Strict or a custom request-header check.

Q3: What if Nginx Referer checks block legitimate requests?

Enable the check only on writes (POST/PUT/DELETE) and admin paths. Do not check GET or static assets. For multiple sites on the same origin, add every trusted domain to the allowlist.

Summary

Layer CSRF defense: application synchronizer tokens are the foundation, SameSite cookies are the browser-level fallback, Nginx Referer checks add defense in depth. Combined they cover most CSRF cases. Enable them gradually in production and regress with automated security tests.