Bearsampp 2026.3.26
API documentation
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 getAllHeaders ()

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 252 of file class.csrf.php.

253 {
254 if (!isset($_SESSION[self::SESSION_KEY])) {
255 return 0;
256 }
257
258 $removed = 0;
259 $currentTime = time();
260
261 foreach ($_SESSION[self::SESSION_KEY] as $token => $timestamp) {
262 if ($currentTime - $timestamp > self::TOKEN_EXPIRATION) {
263 unset($_SESSION[self::SESSION_KEY][$token]);
264 $removed++;
265 }
266 }
267
268 if ($removed > 0) {
269 Util::logDebug("Cleaned up $removed expired CSRF tokens");
270 }
271
272 return $removed;
273 }
static logDebug($data, $file=null)

References Util\logDebug().

Referenced by init().

◆ 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 80 of file class.csrf.php.

81 {
82 self::init();
83
84 try {
85 // Generate cryptographically secure random token
86 $token = bin2hex(random_bytes(32));
87 } catch (Exception $e) {
88 Util::logError('Failed to generate CSRF token: ' . $e->getMessage());
89 // Fallback to less secure but functional method
90 $token = hash('sha256', uniqid('bearsampp_csrf_', true) . microtime(true));
91 }
92
93 // Store token with timestamp
94 $_SESSION[self::SESSION_KEY][$token] = time();
95
96 // Limit number of stored tokens
97 if (count($_SESSION[self::SESSION_KEY]) > self::MAX_TOKENS) {
98 // Remove oldest token
99 $oldestToken = array_key_first($_SESSION[self::SESSION_KEY]);
100 unset($_SESSION[self::SESSION_KEY][$oldestToken]);
101 }
102
103 // Log token generation without exposing token material
104 Util::logDebug('CSRF token generated successfully');
105
106 return $token;
107 }
static init()
static logError($data, $file=null)

References init(), Util\logDebug(), and Util\logError().

Referenced by getToken(), and regenerateToken().

◆ 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 218 of file class.csrf.php.

219 {
220 // Use getallheaders() if available (Apache)
221 if (function_exists('getallheaders')) {
222 $headers = getallheaders();
223 if ($headers !== false) {
224 return $headers;
225 }
226 }
227
228 // Fallback for FastCGI/CGI environments
229 $headers = [];
230 foreach ($_SERVER as $key => $value) {
231 // Extract HTTP headers from $_SERVER
232 if (substr($key, 0, 5) === 'HTTP_') {
233 // Convert HTTP_X_CSRF_TOKEN to X-Csrf-Token
234 $headerName = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($key, 5)))));
235 $headers[$headerName] = $value;
236 }
237 // Handle CONTENT_TYPE and CONTENT_LENGTH specially
238 elseif (in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH'])) {
239 $headerName = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))));
240 $headers[$headerName] = $value;
241 }
242 }
243
244 return $headers;
245 }

Referenced by validateRequest().

◆ getStats()

getStats ( )
static

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

Returns
array Statistics about tokens

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

342 {
343 self::init();
344
345 $tokens = $_SESSION[self::SESSION_KEY] ?? [];
346 $currentTime = time();
347 $expired = 0;
348 $valid = 0;
349
350 foreach ($tokens as $timestamp) {
351 if ($currentTime - $timestamp > self::TOKEN_EXPIRATION) {
352 $expired++;
353 } else {
354 $valid++;
355 }
356 }
357
358 return [
359 'total' => count($tokens),
360 'valid' => $valid,
361 'expired' => $expired,
362 'max_tokens' => self::MAX_TOKENS,
363 'expiration_seconds' => self::TOKEN_EXPIRATION
364 ];
365 }

References init().

◆ getToken()

getToken ( )
static

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

Returns
string The CSRF token

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

115 {
116 self::init();
117
118 // If no tokens exist, generate one
119 if (empty($_SESSION[self::SESSION_KEY])) {
120 return self::generateToken();
121 }
122
123 // Return the most recent token
124 $tokens = $_SESSION[self::SESSION_KEY];
125 end($tokens);
126 $latestToken = key($tokens);
127
128 // Check if latest token is expired
129 if (time() - $tokens[$latestToken] > self::TOKEN_EXPIRATION) {
130 // Generate new token if expired
131 return self::generateToken();
132 }
133
134 return $latestToken;
135 }
static generateToken()

References generateToken(), and init().

Referenced by getTokenField(), and getTokenMeta().

◆ getTokenField()

getTokenField ( )
static

Gets the token as a hidden input field for forms.

Returns
string HTML hidden input field

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

298 {
299 $token = self::getToken();
300 return '<input type="hidden" name="csrf_token" value="' . htmlspecialchars($token, ENT_QUOTES, 'UTF-8') . '">';
301 }

References getToken().

◆ 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 309 of file class.csrf.php.

310 {
311 $token = self::getToken();
312 return '<meta name="csrf-token" content="' . htmlspecialchars($token, ENT_QUOTES, 'UTF-8') . '">';
313 }

References getToken().

◆ 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 // Start session if not already started
61 if (session_status() === PHP_SESSION_NONE) {
62 session_start();
63 }
64
65 // Initialize token storage if not exists
66 if (!isset($_SESSION[self::SESSION_KEY])) {
67 $_SESSION[self::SESSION_KEY] = [];
68 }
69
70 // Clean up expired tokens
72 }
static cleanupExpiredTokens()

References cleanupExpiredTokens().

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

◆ regenerateToken()

regenerateToken ( )
static

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

Returns
string The new CSRF token

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

282 {
283 self::init();
284
285 // Clear all existing tokens
286 $_SESSION[self::SESSION_KEY] = [];
287
288 // Generate new token
289 return self::generateToken();
290 }

References generateToken(), and init().

◆ 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 322 of file class.csrf.php.

323 {
324 if (!self::validateRequest($removeAfterValidation)) {
325 http_response_code(403);
326 header('Content-Type: application/json');
327 echo json_encode([
328 'error' => 'CSRF validation failed',
329 'message' => 'Invalid or expired security token. Please refresh the page and try again.'
330 ]);
331 exit;
332 }
333 }

References exit.

◆ validateRequest()

validateRequest ( $removeAfterValidation = false)
static

Validates a CSRF token from the request (POST or GET). Checks $_POST['csrf_token'] first, then $_GET['csrf_token'], then headers.

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

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

187 {
188 // Check POST first (most common for AJAX)
189 if (isset($_POST['csrf_token'])) {
190 return self::validateToken($_POST['csrf_token'], $removeAfterValidation);
191 }
192
193 // Check GET as fallback
194 if (isset($_GET['csrf_token'])) {
195 return self::validateToken($_GET['csrf_token'], $removeAfterValidation);
196 }
197
198 // Check custom header (for AJAX requests)
199 $headers = self::getAllHeaders();
200
201 // Check for X-CSRF-Token header (case-insensitive)
202 foreach ($headers as $key => $value) {
203 if (strtolower($key) === 'x-csrf-token') {
204 return self::validateToken($value, $removeAfterValidation);
205 }
206 }
207
208 Util::logWarning('CSRF validation failed: No token in request');
209 return false;
210 }
static getAllHeaders()
static logWarning($data, $file=null)

References getAllHeaders(), Util\logWarning(), and validateToken().

◆ 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 144 of file class.csrf.php.

145 {
146 self::init();
147
148 // Check if token is provided
149 if (empty($token) || !is_string($token)) {
150 Util::logWarning('CSRF validation failed: No token provided');
151 return false;
152 }
153
154 // Check if token exists in session
155 if (!isset($_SESSION[self::SESSION_KEY][$token])) {
156 Util::logWarning('CSRF validation failed: Token not found in session');
157 return false;
158 }
159
160 // Check if token is expired
161 $tokenTimestamp = $_SESSION[self::SESSION_KEY][$token];
162 if (time() - $tokenTimestamp > self::TOKEN_EXPIRATION) {
163 Util::logWarning('CSRF validation failed: Token expired');
164 unset($_SESSION[self::SESSION_KEY][$token]);
165 return false;
166 }
167
168 // Token is valid
169 Util::logDebug('CSRF token validated successfully');
170
171 // Remove token if one-time use is requested
172 if ($removeAfterValidation) {
173 unset($_SESSION[self::SESSION_KEY][$token]);
174 }
175
176 return true;
177 }

References init(), Util\logDebug(), and Util\logWarning().

Referenced by validateRequest().

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: