PHP CSRF Protection
A CSRF check helps distinguish a legitimate form submission from a request caused by another site. Bind the token to the visitor’s server-side session and verify it before changing state.
How it works
Generate an unpredictable token, retain it server-side and return it to the intended form/client. On POST, require a scalar token and compare it using hash_equals with the stored value first. The JSON GET in this standalone lab makes the mechanism easy to test; a normal HTML form can carry the token in a hidden input. CSRF protection does not authenticate the visitor or replace authorisation, and cross-site scripting can undermine a token-based defence.
Run it locally
Save this standalone lab file in a separate local folder. Start a PHP development server on an unused loopback port, for example php -S 127.0.0.1:8090 -t . . Open the shown filename through that server, not a file URL. Exercise GET and POST as described. This is not a POST endpoint on Bhylu, and the built-in development server is not a production server.
php -l csrf.php
php -S 127.0.0.1:8090 -t .Download this source as a local PHP lab file. Keep lab files separate from the Bhylu project and production data.
Example
<?php
declare(strict_types=1);
session_set_cookie_params(["httponly"=>true,"samesite"=>"Lax","secure"=>isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off"]);
session_start();
$_SESSION["lab_csrf"] ??= bin2hex(random_bytes(32));
header("Content-Type: application/json; charset=utf-8");
if (($_SERVER["REQUEST_METHOD"] ?? "GET") === "GET") { echo json_encode(["token"=>$_SESSION["lab_csrf"]]); exit; }
if ($_SERVER["REQUEST_METHOD"] !== "POST") { http_response_code(405); echo json_encode(["error"=>"Use POST"]); exit; }
$token = $_POST["token"] ?? null;
if (!is_string($token) || !hash_equals($_SESSION["lab_csrf"], $token)) { http_response_code(403); echo json_encode(["error"=>"Invalid token"]); exit; }
echo json_encode(["accepted"=>true]);
Expected result
GET supplies a session token; a matching POST returns {"accepted":true}; missing tokens return 403.The review retains the session cookie, reads the actual generated token and exercises accepted and rejected POSTs. No loan is created by this fixture. A production flow must decide token lifetime, session expiry and the complete set of protected state-changing endpoints instead of checking only one convenient form.
Requests to check
GET csrf.php→ status 200; retain the actual returned token and session cookie for the next request.POST csrf.php→ status 403; form fields: .POST csrf.php→ status 200; form fields: token.
Use a local browser form or HTTP client. A CSRF token from one session does not authorise a different session. The automated review uses actual HTTP requests, not just command-line output.
Check the official PHP manual for detailed version and API contracts.