PHP
Implement Anti-CSRF Tokens for Secure Form Submissions
Protect web forms from CSRF attacks. Learn to generate and validate unique, session-based CSRF tokens in PHP, enhancing your application's overall security.
<?php
session_start();
// Function to generate a CSRF token
function generateCsrfToken() {
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32)); // Generate a cryptographically secure token
}
return $_SESSION['csrf_token'];
}
// Function to validate a CSRF token
function validateCsrfToken($token) {
if (!empty($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token)) {
// Token is valid. Invalidate it after use to prevent replay attacks.
unset($_SESSION['csrf_token']);
return true;
}
return false;
}
// --- Example Usage ---
// 1. Generate token and include in form
$csrfToken = generateCsrfToken();
?>
<form action="process.php" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
<label for="message">Message:</label>
<input type="text" id="message" name="message">
<button type="submit">Submit</button>
</form>
<?php
// 2. In process.php or after form submission on the same page:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$submittedToken = $_POST['csrf_token'] ?? '';
if (validateCsrfToken($submittedToken)) {
echo "Form submitted securely. Processing data...
";
// Process the form data here
// e.g., save message: htmlspecialchars($_POST['message'])
} else {
http_response_code(403); // Forbidden
echo "Invalid CSRF token. Request blocked.
";
// Optionally redirect or log
}
}
?>
How it works: This PHP snippet illustrates how to implement anti-CSRF (Cross-Site Request Forgery) protection. It involves generating a unique, cryptographically secure token stored in the user's session (`generateCsrfToken`). This token is then embedded as a hidden field in forms. Upon form submission, the `validateCsrfToken` function compares the submitted token with the one in the session. If they match, the request is legitimate; otherwise, it's a potential CSRF attack and is blocked. `hash_equals` is used for constant-time comparison to prevent timing attacks.