Bearsampp 2026.9.23
Loading...
Searching...
No Matches
Csrf Class Reference

Static Public Member Functions

static generateToken ()
static getStats ()
static getToken ()
static getTokenField ()
static getTokenMeta ()
static init ()
static regenerateToken ()
static validateOrDie ($removeAfterValidation=false)
static validateRequest ($removeAfterValidation=false)
static validateToken ($token, $removeAfterValidation=false)

Data Fields

const MAX_TOKENS = 10
const SESSION_KEY = 'bearsampp_csrf_tokens'
const TOKEN_EXPIRATION = 7200

Static Private Member Functions

static cleanupExpiredTokens ()
static configureSession ()
static getAllHeaders ()
static getAllowedHosts ()
static getOriginPort (array $parts, $scheme)
static getRequestPort ($httpHost, $scheme)
static isAllowedOrigin ($url, $httpHost, $scheme, array $allowedHosts)
static isHostAllowed ($host, array $allowedHosts)
static normalizeHost ($host)
static validateOrigin ()

Detailed Description

Class Csrf

Provides CSRF (Cross-Site Request Forgery) protection for the Bearsampp application. This class handles token generation, validation, and management to prevent CSRF attacks.

Features:

  • Secure token generation using cryptographically secure random bytes
  • Session-based token storage
  • Token expiration (default: 2 hours)
  • Token regeneration for enhanced security
  • Automatic cleanup of expired tokens

Usage:

// Generate and get token for forms/AJAX
$token = Csrf::getToken();
// Validate token from request
if (!Csrf::validateToken($_POST['csrf_token'])) {
die('CSRF validation failed');
}
static getToken()
static validateToken($token, $removeAfterValidation=false)

Definition at line 34 of file class.csrf.php.

Member Function Documentation

◆ cleanupExpiredTokens()

cleanupExpiredTokens ( )
staticprivate

Removes expired tokens from the session.

Returns
int Number of tokens removed

Definition at line 606 of file class.csrf.php.

607 {
608 if (!isset($_SESSION[self::SESSION_KEY])) {
609 return 0;
610 }
611
612 $removed = 0;
613 $currentTime = time();
614
615 foreach ($_SESSION[self::SESSION_KEY] as $token => $timestamp) {
616 if ($currentTime - $timestamp > self::TOKEN_EXPIRATION) {
617 unset($_SESSION[self::SESSION_KEY][$token]);
618 $removed++;
619 }
620 }
621
622 if ($removed > 0) {
623 Log::debug("Cleaned up $removed expired CSRF tokens");
624 }
625
626 return $removed;
627 }
static debug($data, $file=null)

References Log\debug().

Referenced by init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ configureSession()

configureSession ( )
staticprivate

Hardens the session configuration before a session is started. These settings are also present in the bundled php.ini, but are applied here as defense in depth in case that file is customized.

Returns
void

Definition at line 84 of file class.csrf.php.

85 {
86 // Only relevant before the session has been started
87 if (session_status() !== PHP_SESSION_NONE || session_id() !== '') {
88 return;
89 }
90
91 $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
92
93 session_set_cookie_params([
94 'lifetime' => 0,
95 'path' => '/',
96 'secure' => $secure,
97 'httponly' => true,
98 'samesite' => 'Strict'
99 ]);
100
101 ini_set('session.use_only_cookies', '1');
102 ini_set('session.use_strict_mode', '1');
103 }

Referenced by init().

Here is the caller graph for this function:

◆ generateToken()

generateToken ( )
static

Generates a new CSRF token and stores it in the session.

Returns
string The generated CSRF token
Exceptions
ExceptionIf random_bytes() fails

Definition at line 111 of file class.csrf.php.

112 {
113 self::init();
114
115 // Fail closed: never fall back to weak randomness. random_bytes()
116 // throws if no secure source of entropy is available.
117 $token = bin2hex(random_bytes(32));
118
119 // Store token with timestamp
120 $_SESSION[self::SESSION_KEY][$token] = time();
121
122 // Limit number of stored tokens
123 if (count($_SESSION[self::SESSION_KEY]) > self::MAX_TOKENS) {
124 // Remove oldest token
125 $oldestToken = array_key_first($_SESSION[self::SESSION_KEY]);
126 unset($_SESSION[self::SESSION_KEY][$oldestToken]);
127 }
128
129 // Log token generation without exposing token material
130 Log::debug('CSRF token generated successfully');
131
132 return $token;
133 }
static init()

References Log\debug(), and init().

Referenced by getToken(), and regenerateToken().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getAllHeaders()

getAllHeaders ( )
staticprivate

Gets all HTTP headers in a cross-compatible way. Works with both Apache and FastCGI/CGI environments.

Returns
array Associative array of headers

Definition at line 573 of file class.csrf.php.

574 {
575 // Use getallheaders() if available (Apache)
576 if (function_exists('getallheaders')) {
577 $headers = getallheaders();
578 if ($headers !== false) {
579 return $headers;
580 }
581 }
582
583 // Fallback for FastCGI/CGI environments
584 $headers = [];
585 foreach ($_SERVER as $key => $value) {
586 // Extract HTTP headers from $_SERVER
587 if (substr($key, 0, 5) === 'HTTP_') {
588 // Convert HTTP_X_CSRF_TOKEN to X-Csrf-Token
589 $headerName = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($key, 5)))));
590 $headers[$headerName] = $value;
591 } // Handle CONTENT_TYPE and CONTENT_LENGTH specially
592 elseif (in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH'])) {
593 $headerName = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))));
594 $headers[$headerName] = $value;
595 }
596 }
597
598 return $headers;
599 }

Referenced by validateRequest().

Here is the caller graph for this function:

◆ getAllowedHosts()

getAllowedHosts ( )
staticprivate

Builds the allowlist of hosts the local server is intended to serve. Keeps DNS-rebinding protection effective while still allowing access through the machine hostname and any user-configured virtual hosts.

Returns
array List of allowed, normalized host names.

Definition at line 311 of file class.csrf.php.

312 {
313 $allowed = array('localhost', APP_LOCALHOST, '[::1]', '::1');
314
315 // The local address this very request was received on. This is the
316 // reachable address (e.g. a LAN IP) clients use when the application
317 // has been put online, so requests addressed to the server's own
318 // reachable addresses must be accepted.
319 if (isset($_SERVER['SERVER_ADDR'])) {
320 $serverAddr = self::normalizeHost((string)$_SERVER['SERVER_ADDR']);
321 if ($serverAddr !== '') {
322 $allowed[] = $serverAddr;
323 }
324 }
325
326 $hostname = function_exists('gethostname') ? @gethostname() : false;
327 if ($hostname !== false && $hostname !== '') {
328 $allowed[] = self::normalizeHost($hostname);
329 }
330
331 global $bearsamppConfig;
332 if (is_object($bearsamppConfig) && method_exists($bearsamppConfig, 'getHostname')) {
333 $cfgHostname = $bearsamppConfig->getHostname();
334 if (is_string($cfgHostname) && $cfgHostname !== '') {
335 $allowed[] = self::normalizeHost($cfgHostname);
336 }
337 }
338
339 global $bearsamppBins;
340 if (is_object($bearsamppBins) && method_exists($bearsamppBins, 'getApache')) {
341 try {
342 $apache = $bearsamppBins->getApache();
343 if (is_object($apache) && method_exists($apache, 'getVhosts')) {
344 $vhostNames = array();
345 foreach ($apache->getVhosts() as $vhost) {
346 if (is_string($vhost) && $vhost !== '') {
347 $vhostNames[] = $vhost;
348 }
349 }
350
351 // Resolve the actual host names each vhost config serves.
352 // Relying on the config file names alone would miss ServerAlias
353 // entries and hosts that differ from the file name, which would
354 // wrongly reject legitimate requests when HTTPS (secure Apache
355 // settings) is used.
356 $parsedHosts = array();
357 $vhostsPath = Path::getVhostsPath();
358 if (is_dir($vhostsPath)) {
359 foreach ($vhostNames as $vhost) {
360 $content = @file_get_contents($vhostsPath . '/' . $vhost . '.conf');
361 if ($content === false) {
362 // Fall back to the config file name when it cannot be read
363 $parsedHosts[] = $vhost;
364 continue;
365 }
366
367 $found = false;
368 foreach (array('ServerName', 'ServerAlias') as $directive) {
369 if (preg_match_all('/^\s*' . $directive . '\s+([^\s#]+)/mi', $content, $matches)) {
370 foreach ($matches[1] as $declaredHost) {
371 $normalized = self::normalizeHost($declaredHost);
372 if ($normalized !== '') {
373 $parsedHosts[] = $normalized;
374 $found = true;
375 }
376 }
377 }
378 }
379
380 // Keep the file name when the config declares no host name
381 if (!$found) {
382 $parsedHosts[] = $vhost;
383 }
384 }
385 }
386
387 foreach (array_unique($parsedHosts) as $vhost) {
388 $allowed[] = $vhost;
389 // Vhost certificates cover any subdomain (e.g. www.vhost.local),
390 // so those hosts must be accepted as well.
391 $allowed[] = '*.' . $vhost;
392 }
393 }
394 } catch (\Throwable $e) {
395 // Host discovery must never break CSRF validation
396 Log::warning('CSRF validation failed: Unable to read virtual hosts: ' . $e->getMessage());
397 }
398 }
399
400 return array_values(array_unique($allowed));
401 }
global $bearsamppBins
static normalizeHost($host)
static warning($data, $file=null)
static getVhostsPath($aetrayPath=false)
global $bearsamppConfig
Definition homepage.php:46
const APP_LOCALHOST
Definition root.php:21

References $bearsamppBins, $bearsamppConfig, APP_LOCALHOST, Path\getVhostsPath(), normalizeHost(), and Log\warning().

Referenced by validateOrigin().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getOriginPort()

getOriginPort ( array $parts,
$scheme )
staticprivate

Resolves the effective port of an Origin/Referer URL, falling back to the default port of the scheme when none is explicitly present.

Parameters
array$partsThe parsed URL components.
string$schemeThe origin scheme ('http' or 'https').
Returns
int The effective port.

Definition at line 540 of file class.csrf.php.

541 {
542 if (isset($parts['port']) && is_numeric($parts['port'])) {
543 return (int)$parts['port'];
544 }
545
546 return $scheme === 'https' ? 443 : 80;
547 }

◆ getRequestPort()

getRequestPort ( $httpHost,
$scheme )
staticprivate

Resolves the effective port of the request from the HTTP_HOST header, falling back to the default port of the scheme when none is present.

Parameters
string$httpHostThe raw HTTP_HOST header (may include a port).
string$schemeThe request scheme ('http' or 'https').
Returns
int The effective port.

Definition at line 558 of file class.csrf.php.

559 {
560 if (preg_match('/:(\d+)$/', $httpHost, $matches)) {
561 return (int)$matches[1];
562 }
563
564 return $scheme === 'https' ? 443 : 80;
565 }

◆ getStats()

getStats ( )
static

Gets statistics about current CSRF tokens. Useful for debugging and monitoring.

Returns
array Statistics about tokens

Definition at line 698 of file class.csrf.php.

699 {
700 self::init();
701
702 $tokens = $_SESSION[self::SESSION_KEY] ?? [];
703 $currentTime = time();
704 $expired = 0;
705 $valid = 0;
706
707 foreach ($tokens as $timestamp) {
708 if ($currentTime - $timestamp > self::TOKEN_EXPIRATION) {
709 $expired++;
710 } else {
711 $valid++;
712 }
713 }
714
715 return [
716 'total' => count($tokens),
717 'valid' => $valid,
718 'expired' => $expired,
719 'max_tokens' => self::MAX_TOKENS,
720 'expiration_seconds' => self::TOKEN_EXPIRATION
721 ];
722 }

References init().

Here is the call graph for this function:

◆ getToken()

getToken ( )
static

Gets the current CSRF token, generating a new one if none exists.

Returns
string The CSRF token

Definition at line 140 of file class.csrf.php.

141 {
142 self::init();
143
144 // If no tokens exist, generate one
145 if (empty($_SESSION[self::SESSION_KEY])) {
146 return self::generateToken();
147 }
148
149 // Return the most recent token
150 $tokens = $_SESSION[self::SESSION_KEY];
151 end($tokens);
152 $latestToken = key($tokens);
153
154 // Check if latest token is expired
155 if (time() - $tokens[$latestToken] > self::TOKEN_EXPIRATION) {
156 // Generate new token if expired
157 return self::generateToken();
158 }
159
160 return $latestToken;
161 }
static generateToken()

References generateToken(), and init().

Referenced by getTokenField(), and getTokenMeta().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getTokenField()

getTokenField ( )
static

Gets the token as a hidden input field for forms.

Returns
string HTML hidden input field

Definition at line 651 of file class.csrf.php.

652 {
653 $token = self::getToken();
654
655 return '<input type="hidden" name="csrf_token" value="' . htmlspecialchars($token, ENT_QUOTES, 'UTF-8') . '">';
656 }

References getToken().

Here is the call graph for this function:

◆ getTokenMeta()

getTokenMeta ( )
static

Gets the token as a meta tag for inclusion in HTML head. Useful for AJAX requests.

Returns
string HTML meta tag

Definition at line 664 of file class.csrf.php.

665 {
666 $token = self::getToken();
667
668 return '<meta name="csrf-token" content="' . htmlspecialchars($token, ENT_QUOTES, 'UTF-8') . '">';
669 }

References getToken().

Here is the call graph for this function:

◆ init()

init ( )
static

Initializes the CSRF protection system. Starts the session if not already started and cleans up expired tokens.

Returns
void

Definition at line 58 of file class.csrf.php.

59 {
60 // Harden session settings before the session is started
62
63 // Start session if not already started
64 if (session_status() === PHP_SESSION_NONE) {
65 session_start();
66 }
67
68 // Initialize token storage if not exists
69 if (!isset($_SESSION[self::SESSION_KEY])) {
70 $_SESSION[self::SESSION_KEY] = [];
71 }
72
73 // Clean up expired tokens
75 }
static cleanupExpiredTokens()
static configureSession()

References cleanupExpiredTokens(), and configureSession().

Referenced by generateToken(), getStats(), getToken(), regenerateToken(), and validateToken().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isAllowedOrigin()

isAllowedOrigin ( $url,
$httpHost,
$scheme,
array $allowedHosts )
staticprivate

Checks that an Origin/Referer URL belongs to an allowed host and matches the scheme, host and effective port the request was addressed to.

Parameters
string$urlThe Origin or Referer header value.
string$httpHostThe raw HTTP_HOST header (may include a port).
string$schemeThe request scheme ('http' or 'https').
array$allowedHostsThe allowlist of permitted hosts.
Returns
bool True if the origin is allowed, false otherwise.

Definition at line 475 of file class.csrf.php.

476 {
477 $parts = parse_url($url);
478 if ($parts === false || empty($parts['host'])) {
479 Log::warning('CSRF validation failed: Unparseable Origin/Referer header');
480
481 return false;
482 }
483
484 // Reject URLs carrying credentials (userinfo). Real browser Origins
485 // never contain them, so this is purely defense in depth.
486 if (isset($parts['user']) || isset($parts['pass'])) {
487 Log::warning('CSRF validation failed: Origin/Referer header must not contain credentials');
488
489 return false;
490 }
491
492 $originScheme = isset($parts['scheme']) ? strtolower($parts['scheme']) : '';
493 if (!in_array($originScheme, array('http', 'https'), true)) {
494 Log::warning('CSRF validation failed: Unsupported Origin/Referer scheme "' . $originScheme . '"');
495
496 return false;
497 }
498
499 $originHost = self::normalizeHost($parts['host']);
500 if (!self::isHostAllowed($originHost, $allowedHosts)) {
501 Log::warning('CSRF validation failed: Origin/Referer host "' . $originHost . '" is not an allowed host');
502
503 return false;
504 }
505
506 // The scheme of the origin must match the scheme the request was made over
507 if ($originScheme !== $scheme) {
508 Log::warning('CSRF validation failed: Origin/Referer scheme "' . $originScheme . '" does not match request scheme "' . $scheme . '"');
509
510 return false;
511 }
512
513 // The origin host must match the host the request was addressed to
514 $requestHost = self::normalizeHost($httpHost);
515 if ($originHost !== $requestHost) {
516 Log::warning('CSRF validation failed: Origin/Referer host "' . $originHost . '" does not match request host "' . $requestHost . '"');
517
518 return false;
519 }
520
521 // The effective port of the origin must match the request port
522 if (self::getOriginPort($parts, $originScheme) !== self::getRequestPort($httpHost, $scheme)) {
523 Log::warning('CSRF validation failed: Origin/Referer port mismatch');
524
525 return false;
526 }
527
528 return true;
529 }

References normalizeHost(), and Log\warning().

Referenced by validateOrigin().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isHostAllowed()

isHostAllowed ( $host,
array $allowedHosts )
staticprivate

Checks whether a host is allowed, either by exact match against the allowlist or as a subdomain of an allowed wildcard host (e.g. www.vhost.local matches *.vhost.local). Wildcards mirror the certificate coverage BearSampp generates for virtual hosts.

Parameters
string$hostThe raw host to check.
array$allowedHostsThe allowlist of normalized hosts and wildcards.
Returns
bool True if the host is allowed, false otherwise.

Definition at line 414 of file class.csrf.php.

415 {
416 $host = self::normalizeHost($host);
417 if ($host === '') {
418 return false;
419 }
420
421 if (in_array($host, $allowedHosts, true)) {
422 return true;
423 }
424
425 foreach ($allowedHosts as $allowedHost) {
426 if (strpos($allowedHost, '*.') === 0) {
427 $suffix = substr($allowedHost, 1);
428 if ($suffix !== '' && substr($host, -strlen($suffix)) === $suffix) {
429 return true;
430 }
431 }
432 }
433
434 return false;
435 }

References normalizeHost().

Here is the call graph for this function:

◆ normalizeHost()

normalizeHost ( $host)
staticprivate

Normalizes a host header/name to a comparable form: lowercased, with any explicit port removed and IPv6 addresses bracketed ([::1]).

Parameters
string$hostThe raw host.
Returns
string The normalized host.

Definition at line 445 of file class.csrf.php.

446 {
447 $host = strtolower(trim((string)$host));
448
449 // Strip a trailing port (both host:port and [ipv6]:port forms)
450 if (preg_match('/^\‍[.*\‍]:\d+$/', $host)) {
451 $host = substr($host, 0, strrpos($host, ':'));
452 } elseif (preg_match('/^[^:]+:\d+$/', $host)) {
453 $host = substr($host, 0, strrpos($host, ':'));
454 }
455
456 // Bracket IPv6 loopback so ::1 and [::1] compare equal
457 if ($host === '::1') {
458 $host = '[::1]';
459 }
460
461 return $host;
462 }

Referenced by getAllowedHosts(), isAllowedOrigin(), isHostAllowed(), and validateOrigin().

Here is the caller graph for this function:

◆ regenerateToken()

regenerateToken ( )
static

Regenerates the CSRF token. Useful after sensitive operations or login.

Returns
string The new CSRF token

Definition at line 635 of file class.csrf.php.

636 {
637 self::init();
638
639 // Clear all existing tokens
640 $_SESSION[self::SESSION_KEY] = [];
641
642 // Generate new token
643 return self::generateToken();
644 }

References generateToken(), and init().

Here is the call graph for this function:

◆ validateOrDie()

validateOrDie ( $removeAfterValidation = false)
static

Validates request and sends JSON error response if validation fails. This is a convenience method for AJAX endpoints.

Parameters
bool$removeAfterValidationWhether to remove the token after successful validation
Returns
void Exits with JSON error if validation fails

Definition at line 679 of file class.csrf.php.

680 {
681 if (!self::validateRequest($removeAfterValidation)) {
682 http_response_code(403);
683 header('Content-Type: application/json');
684 echo json_encode([
685 'error' => 'CSRF validation failed',
686 'message' => 'Invalid or expired security token. Please refresh the page and try again.'
687 ]);
688 exit;
689 }
690 }

References exit.

◆ validateOrigin()

validateOrigin ( )
staticprivate

Validates that the request is addressed to an intended/trusted host and originates from that same origin.

The request host (HTTP_HOST) must be part of a fixed allowlist of hosts the local server is meant to serve (localhost, 127.0.0.1, ::1, the machine hostname and any configured virtual hosts). Comparing the Origin header against an attacker-influenced HTTP_HOST alone would not stop DNS-rebinding attacks, where a malicious domain is pointed at 127.0.0.1 and both the Host and Origin headers are controlled by the attacker.

Uses the Origin header when present and falls back to the Referer header. Browsers always send Origin on cross-origin POST requests, so a missing Origin/Referer on a state-changing request is treated as invalid.

Returns
bool True if the request is same-origin, false otherwise

Definition at line 266 of file class.csrf.php.

267 {
268 $httpHost = isset($_SERVER['HTTP_HOST']) ? (string)$_SERVER['HTTP_HOST'] : '';
269 if ($httpHost === '') {
270 Log::warning('CSRF validation failed: HTTP_HOST not available');
271
272 return false;
273 }
274
275 $allowedHosts = self::getAllowedHosts();
276
277 // The request must be addressed to an intended host. This is the key
278 // defense against DNS rebinding: an attacker's domain, even resolved
279 // to 127.0.0.1, will not be in the allowlist.
280 $requestHost = self::normalizeHost($httpHost);
281 if (!self::isHostAllowed($requestHost, $allowedHosts)) {
282 Log::warning('CSRF validation failed: Request host "' . $requestHost . '" is not an allowed host');
283
284 return false;
285 }
286
287 $scheme = (!empty($_SERVER['HTTPS']) && strtolower((string)$_SERVER['HTTPS']) !== 'off') ? 'https' : 'http';
288
289 $origin = isset($_SERVER['HTTP_ORIGIN']) ? (string)$_SERVER['HTTP_ORIGIN'] : '';
290 if ($origin !== '') {
291 return self::isAllowedOrigin($origin, $httpHost, $scheme, $allowedHosts);
292 }
293
294 $referer = isset($_SERVER['HTTP_REFERER']) ? (string)$_SERVER['HTTP_REFERER'] : '';
295 if ($referer !== '') {
296 return self::isAllowedOrigin($referer, $httpHost, $scheme, $allowedHosts);
297 }
298
299 Log::warning('CSRF validation failed: Missing Origin and Referer headers');
300
301 return false;
302 }
static isAllowedOrigin($url, $httpHost, $scheme, array $allowedHosts)
static getAllowedHosts()

References getAllowedHosts(), isAllowedOrigin(), normalizeHost(), and Log\warning().

Here is the call graph for this function:

◆ validateRequest()

validateRequest ( $removeAfterValidation = false)
static

Validates a CSRF token from the request (POST body or header). Checks $_POST['csrf_token'] first, then the X-CSRF-Token header. Also verifies the request is same-origin.

Parameters
bool$removeAfterValidationWhether to remove the token after successful validation
Returns
bool True if token is valid, false otherwise

Definition at line 218 of file class.csrf.php.

219 {
220 // Reject cross-origin requests before checking the token.
221 // Combined with SameSite=Strict cookies this blocks classic CSRF and
222 // DNS-rebinding attacks.
223 if (!self::validateOrigin()) {
224 return false;
225 }
226
227 // Accept the token from the POST body or a dedicated header only.
228 // Tokens in the query string leak via Referer headers, logs and
229 // browser history.
230 if (isset($_POST['csrf_token'])) {
231 return self::validateToken($_POST['csrf_token'], $removeAfterValidation);
232 }
233
234 // Check custom header (for AJAX requests)
235 $headers = self::getAllHeaders();
236
237 // Check for X-CSRF-Token header (case-insensitive)
238 foreach ($headers as $key => $value) {
239 if (strtolower($key) === 'x-csrf-token') {
240 return self::validateToken($value, $removeAfterValidation);
241 }
242 }
243
244 Log::warning('CSRF validation failed: No token in request');
245
246 return false;
247 }
static getAllHeaders()

References getAllHeaders(), validateToken(), and Log\warning().

Here is the call graph for this function:

◆ validateToken()

validateToken ( $token,
$removeAfterValidation = false )
static

Validates a CSRF token.

Parameters
string | null$tokenThe token to validate
bool$removeAfterValidationWhether to remove the token after successful validation (one-time use)
Returns
bool True if token is valid, false otherwise

Definition at line 171 of file class.csrf.php.

172 {
173 self::init();
174
175 // Check if token is provided
176 if (empty($token) || !is_string($token)) {
177 Log::warning('CSRF validation failed: No token provided');
178
179 return false;
180 }
181
182 // Check if token exists in session
183 if (!isset($_SESSION[self::SESSION_KEY][$token])) {
184 Log::warning('CSRF validation failed: Token not found in session');
185
186 return false;
187 }
188
189 // Check if token is expired
190 $tokenTimestamp = $_SESSION[self::SESSION_KEY][$token];
191 if (time() - $tokenTimestamp > self::TOKEN_EXPIRATION) {
192 Log::warning('CSRF validation failed: Token expired');
193 unset($_SESSION[self::SESSION_KEY][$token]);
194
195 return false;
196 }
197
198 // Token is valid
199 Log::debug('CSRF token validated successfully');
200
201 // Remove token if one-time use is requested
202 if ($removeAfterValidation) {
203 unset($_SESSION[self::SESSION_KEY][$token]);
204 }
205
206 return true;
207 }

References Log\debug(), init(), and Log\warning().

Referenced by validateRequest().

Here is the call graph for this function:
Here is the caller graph for this function:

Field Documentation

◆ MAX_TOKENS

const MAX_TOKENS = 10

Maximum number of tokens to store per session This prevents session bloat from token accumulation

Definition at line 50 of file class.csrf.php.

◆ SESSION_KEY

const SESSION_KEY = 'bearsampp_csrf_tokens'

Session key for storing CSRF tokens

Definition at line 39 of file class.csrf.php.

◆ TOKEN_EXPIRATION

const TOKEN_EXPIRATION = 7200

Token expiration time in seconds (default: 2 hours)

Definition at line 44 of file class.csrf.php.


The documentation for this class was generated from the following file: