PSR12
This commit is contained in:
291
src/Csrf.php
291
src/Csrf.php
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/** DomFramework
|
||||
* @package domframework
|
||||
* @author Dominique Fournier <dominique@fournier38.fr>
|
||||
@@ -14,156 +15,166 @@ namespace Domframework;
|
||||
*/
|
||||
class Csrf
|
||||
{
|
||||
/** Allow to disable the csrf protection
|
||||
*/
|
||||
public $csrf = TRUE;
|
||||
/** This hidden field name in HTML
|
||||
*/
|
||||
public $field = "CSRF_TOKEN";
|
||||
/** The created token
|
||||
*/
|
||||
private $csrfToken = "";
|
||||
/** Timeout of the CSRF token : 3600s by default (maximum time allowed to
|
||||
* enter information in form and submit) */
|
||||
private $csrfTimeout = 3600;
|
||||
/** Allow to disable the csrf protection
|
||||
*/
|
||||
public $csrf = true;
|
||||
/** This hidden field name in HTML
|
||||
*/
|
||||
public $field = "CSRF_TOKEN";
|
||||
/** The created token
|
||||
*/
|
||||
private $csrfToken = "";
|
||||
/** Timeout of the CSRF token : 3600s by default (maximum time allowed to
|
||||
* enter information in form and submit) */
|
||||
private $csrfTimeout = 3600;
|
||||
|
||||
/** Manage the singleton
|
||||
*/
|
||||
public function __construct ()
|
||||
{
|
||||
if (isset ($GLOBALS["domframework"]["csrf"]))
|
||||
/** Manage the singleton
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->csrfToken = $GLOBALS["domframework"]["csrf"]->csrfToken;
|
||||
$this->field = $GLOBALS["domframework"]["csrf"]->field;
|
||||
$this->csrfTimeout = $GLOBALS["domframework"]["csrf"]->csrfTimeout;
|
||||
if (isset($GLOBALS["domframework"]["csrf"])) {
|
||||
$this->csrfToken = $GLOBALS["domframework"]["csrf"]->csrfToken;
|
||||
$this->field = $GLOBALS["domframework"]["csrf"]->field;
|
||||
$this->csrfTimeout = $GLOBALS["domframework"]["csrf"]->csrfTimeout;
|
||||
} else {
|
||||
$GLOBALS["domframework"]["csrf"] = $this;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
/** Get / Set the status of the CSRF protection
|
||||
* @param boolean|null $val The value to set/get if null
|
||||
*/
|
||||
public function csrfState($val = null)
|
||||
{
|
||||
$GLOBALS["domframework"]["csrf"] = $this;
|
||||
if ($val === null) {
|
||||
return $this->csrf;
|
||||
}
|
||||
$this->csrf = !! $val;
|
||||
$GLOBALS["domframework"]["csrf"] = $this;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get / Set the status of the CSRF protection
|
||||
* @param boolean|null $val The value to set/get if null
|
||||
*/
|
||||
public function csrfState ($val = null)
|
||||
{
|
||||
if ($val === null)
|
||||
return $this->csrf;
|
||||
$this->csrf = !! $val;
|
||||
$GLOBALS["domframework"]["csrf"] = $this;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** Get / Set the name of the field in HTML
|
||||
* @param string|null $val The value to set/get if null
|
||||
*/
|
||||
public function field ($val = null)
|
||||
{
|
||||
if ($val === null)
|
||||
return $this->field;
|
||||
$this->field = $val;
|
||||
$GLOBALS["domframework"]["csrf"] = $this;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** This function return the token
|
||||
*/
|
||||
public function createToken ()
|
||||
{
|
||||
$l = 30; // Number of chars in token
|
||||
$c = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
for ($s = '',
|
||||
$cl = strlen($c)-1, $i = 0; $i < $l; $s .= $c[mt_rand(0, $cl)],
|
||||
++$i);
|
||||
$this->csrfToken = $s;
|
||||
$_SESSION["domframework"]["csrf"][$this->csrfToken] = microtime (TRUE);
|
||||
$GLOBALS["domframework"]["csrf"] = $this;
|
||||
return $this->csrfToken;
|
||||
}
|
||||
|
||||
/** Check if the provided token is the right token, defined last displayed
|
||||
* page
|
||||
* @param string $tokenFromUser The value csrf the user's token
|
||||
*/
|
||||
public function checkToken ($tokenFromUser)
|
||||
{
|
||||
if ($this->csrf === FALSE )
|
||||
return TRUE;
|
||||
// Migrate from unique format to multiple CSRF tokens format
|
||||
// The new format is : array (token => the last used time)
|
||||
if (isset ($_SESSION["domframework"]["csrf"]["csrf"]) &&
|
||||
isset ($_SESSION["domframework"]["csrf"]["csrfStart"]))
|
||||
/** Get / Set the name of the field in HTML
|
||||
* @param string|null $val The value to set/get if null
|
||||
*/
|
||||
public function field($val = null)
|
||||
{
|
||||
$_SESSION["domframework"]["csrf"] = array (
|
||||
$_SESSION["domframework"]["csrf"]["csrf"] =>
|
||||
$_SESSION["domframework"]["csrf"]["csrfStart"]
|
||||
);
|
||||
unset ($_SESSION["domframework"]["csrf"]["csrfStart"]);
|
||||
if ($val === null) {
|
||||
return $this->field;
|
||||
}
|
||||
$this->field = $val;
|
||||
$GLOBALS["domframework"]["csrf"] = $this;
|
||||
return $this;
|
||||
}
|
||||
if (! isset ($_SESSION["domframework"]["csrf"]))
|
||||
{
|
||||
throw new \Exception (dgettext ("domframework",
|
||||
"No previous CSRF token found in session ".
|
||||
"(maybe a new session after expiration ?) : abort"), 406);
|
||||
}
|
||||
if (! key_exists ($tokenFromUser, $_SESSION["domframework"]["csrf"]))
|
||||
{
|
||||
throw new \Exception (dgettext ("domframework",
|
||||
"Invalid CSRF token provided"), 406);
|
||||
}
|
||||
if (($_SESSION["domframework"]["csrf"][$tokenFromUser] + $this->csrfTimeout)
|
||||
< microtime (TRUE))
|
||||
{
|
||||
throw new \Exception (dgettext ("domframework",
|
||||
"Obsolete CSRF token provided"), 406);
|
||||
}
|
||||
// Clean expired tokens (2 times the $this->csrfTimeout)
|
||||
foreach ($_SESSION["domframework"]["csrf"] as $token => $timeout)
|
||||
{
|
||||
if ($timeout + 2 * $this->csrfTimeout < time ())
|
||||
unset ($_SESSION["domframework"]["csrf"][$token]);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Return the CSRF token in a hidden field
|
||||
*/
|
||||
public function displayFormCSRF ()
|
||||
{
|
||||
if ($this->csrfToken == "")
|
||||
$this->createToken ();
|
||||
$res = "<input type='hidden' name='$this->field' ";
|
||||
$res .= "value='$this->csrfToken'/>\n";
|
||||
return $res;
|
||||
}
|
||||
/** This function return the token
|
||||
*/
|
||||
public function createToken()
|
||||
{
|
||||
$l = 30; // Number of chars in token
|
||||
$c = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
for (
|
||||
$s = '',
|
||||
$cl = strlen($c) - 1, $i = 0; $i < $l; $s .= $c[mt_rand(0, $cl)],
|
||||
++$i
|
||||
);
|
||||
$this->csrfToken = $s;
|
||||
$_SESSION["domframework"]["csrf"][$this->csrfToken] = microtime(true);
|
||||
$GLOBALS["domframework"]["csrf"] = $this;
|
||||
return $this->csrfToken;
|
||||
}
|
||||
|
||||
/** Return the token if exists or create a new one if needed
|
||||
*/
|
||||
public function getToken ()
|
||||
{
|
||||
if ($this->csrfToken === "")
|
||||
$this->createToken ();
|
||||
return $this->csrfToken;
|
||||
}
|
||||
/** Check if the provided token is the right token, defined last displayed
|
||||
* page
|
||||
* @param string $tokenFromUser The value csrf the user's token
|
||||
*/
|
||||
public function checkToken($tokenFromUser)
|
||||
{
|
||||
if ($this->csrf === false) {
|
||||
return true;
|
||||
}
|
||||
// Migrate from unique format to multiple CSRF tokens format
|
||||
// The new format is : array (token => the last used time)
|
||||
if (
|
||||
isset($_SESSION["domframework"]["csrf"]["csrf"]) &&
|
||||
isset($_SESSION["domframework"]["csrf"]["csrfStart"])
|
||||
) {
|
||||
$_SESSION["domframework"]["csrf"] = array(
|
||||
$_SESSION["domframework"]["csrf"]["csrf"] =>
|
||||
$_SESSION["domframework"]["csrf"]["csrfStart"]
|
||||
);
|
||||
unset($_SESSION["domframework"]["csrf"]["csrfStart"]);
|
||||
}
|
||||
if (! isset($_SESSION["domframework"]["csrf"])) {
|
||||
throw new \Exception(dgettext(
|
||||
"domframework",
|
||||
"No previous CSRF token found in session " .
|
||||
"(maybe a new session after expiration ?) : abort"
|
||||
), 406);
|
||||
}
|
||||
if (! key_exists($tokenFromUser, $_SESSION["domframework"]["csrf"])) {
|
||||
throw new \Exception(dgettext(
|
||||
"domframework",
|
||||
"Invalid CSRF token provided"
|
||||
), 406);
|
||||
}
|
||||
if (
|
||||
($_SESSION["domframework"]["csrf"][$tokenFromUser] + $this->csrfTimeout)
|
||||
< microtime(true)
|
||||
) {
|
||||
throw new \Exception(dgettext(
|
||||
"domframework",
|
||||
"Obsolete CSRF token provided"
|
||||
), 406);
|
||||
}
|
||||
// Clean expired tokens (2 times the $this->csrfTimeout)
|
||||
foreach ($_SESSION["domframework"]["csrf"] as $token => $timeout) {
|
||||
if ($timeout + 2 * $this->csrfTimeout < time()) {
|
||||
unset($_SESSION["domframework"]["csrf"][$token]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Add more time to existing CSRF token
|
||||
* @param string $tokenFromUser The existing token
|
||||
*/
|
||||
public function extendToken ($tokenFromUser)
|
||||
{
|
||||
$this->checkToken ($tokenFromUser);
|
||||
$_SESSION["domframework"]["csrf"][$tokenFromUser] = microtime (TRUE);
|
||||
return true;
|
||||
}
|
||||
/** Return the CSRF token in a hidden field
|
||||
*/
|
||||
public function displayFormCSRF()
|
||||
{
|
||||
if ($this->csrfToken == "") {
|
||||
$this->createToken();
|
||||
}
|
||||
$res = "<input type='hidden' name='$this->field' ";
|
||||
$res .= "value='$this->csrfToken'/>\n";
|
||||
return $res;
|
||||
}
|
||||
|
||||
/** Check an existing token, then delete it
|
||||
* @param string $tokenFromUser The existing token
|
||||
*/
|
||||
public function checkThenDeleteToken ($tokenFromUser)
|
||||
{
|
||||
$this->checkToken ($tokenFromUser);
|
||||
unset ($_SESSION["domframework"]["csrf"][$tokenFromUser]);
|
||||
return true;
|
||||
}
|
||||
/** Return the token if exists or create a new one if needed
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
if ($this->csrfToken === "") {
|
||||
$this->createToken();
|
||||
}
|
||||
return $this->csrfToken;
|
||||
}
|
||||
|
||||
/** Add more time to existing CSRF token
|
||||
* @param string $tokenFromUser The existing token
|
||||
*/
|
||||
public function extendToken($tokenFromUser)
|
||||
{
|
||||
$this->checkToken($tokenFromUser);
|
||||
$_SESSION["domframework"]["csrf"][$tokenFromUser] = microtime(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Check an existing token, then delete it
|
||||
* @param string $tokenFromUser The existing token
|
||||
*/
|
||||
public function checkThenDeleteToken($tokenFromUser)
|
||||
{
|
||||
$this->checkToken($tokenFromUser);
|
||||
unset($_SESSION["domframework"]["csrf"][$tokenFromUser]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user