csrf : allow multiple browser window by storing multiple CSRF tokens
git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@5458 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
74
csrf.php
74
csrf.php
@@ -11,11 +11,14 @@
|
|||||||
*/
|
*/
|
||||||
class csrf
|
class csrf
|
||||||
{
|
{
|
||||||
/** Allow to disable the csrf protection */
|
/** Allow to disable the csrf protection
|
||||||
public $csrf=TRUE;
|
*/
|
||||||
/** This hidden field name in HTML */
|
public $csrf = TRUE;
|
||||||
|
/** This hidden field name in HTML
|
||||||
|
*/
|
||||||
public $field = "CSRF_TOKEN";
|
public $field = "CSRF_TOKEN";
|
||||||
/** The created token */
|
/** The created token
|
||||||
|
*/
|
||||||
private $csrfToken = "";
|
private $csrfToken = "";
|
||||||
/** Timeout of the CSRF token : 3600s by default (maximum time allowed to
|
/** Timeout of the CSRF token : 3600s by default (maximum time allowed to
|
||||||
* enter information in form and submit) */
|
* enter information in form and submit) */
|
||||||
@@ -39,6 +42,32 @@ class csrf
|
|||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
/** Get / Set the status of the CSRF protection
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
/** This function return the token
|
||||||
*/
|
*/
|
||||||
public function createToken ()
|
public function createToken ()
|
||||||
@@ -50,8 +79,8 @@ class csrf
|
|||||||
$cl = strlen($c)-1, $i = 0; $i < $l; $s .= $c[mt_rand(0, $cl)],
|
$cl = strlen($c)-1, $i = 0; $i < $l; $s .= $c[mt_rand(0, $cl)],
|
||||||
++$i);
|
++$i);
|
||||||
$this->csrfToken = $s;
|
$this->csrfToken = $s;
|
||||||
$_SESSION["domframework"]["csrf"]["csrf"] = $this->csrfToken;
|
$_SESSION["domframework"]["csrf"][$this->csrfToken] = microtime (TRUE);
|
||||||
$_SESSION["domframework"]["csrf"]["csrfStart"] = microtime (TRUE);
|
$GLOBALS["domframework"]["csrf"] = $this;
|
||||||
return $this->csrfToken;
|
return $this->csrfToken;
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
@@ -65,21 +94,36 @@ class csrf
|
|||||||
{
|
{
|
||||||
if ($this->csrf === FALSE )
|
if ($this->csrf === FALSE )
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (! isset ($_SESSION["domframework"]["csrf"]["csrf"]))
|
// Migrate from unique format to multiple CSRF tokens format
|
||||||
|
// The new format is : array (token => the last used time)
|
||||||
|
if (isset ($_SESSION["domframework"]["csrf"]["csrfStart"]))
|
||||||
{
|
{
|
||||||
throw new \Exception (dgettext ("domframework",
|
$_SESSION["domframework"]["csrf"] = array (
|
||||||
"No previous CSRF token : abort"), 406);
|
$_SESSION["domframework"]["csrf"]["csrf"] =>
|
||||||
|
$_SESSION["domframework"]["csrf"]["csrfStart"]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if ($_SESSION["domframework"]["csrf"]["csrf"] !== $tokenFromUser)
|
if (! isset ($_SESSION["domframework"]["csrf"]))
|
||||||
{
|
{
|
||||||
throw new \Exception (dgettext ("domframework",
|
throw new \Exception (dgettext ("domframework",
|
||||||
"Invalid CSRF token provided"), 406);
|
"No previous CSRF token : abort"), 406);
|
||||||
}
|
}
|
||||||
if (($_SESSION["domframework"]["csrf"]["csrfStart"] + $this->csrfTimeout) <
|
if (! key_exists ($tokenFromUser, $_SESSION["domframework"]["csrf"]))
|
||||||
microtime (TRUE))
|
|
||||||
{
|
{
|
||||||
throw new \Exception (dgettext ("domframework",
|
throw new \Exception (dgettext ("domframework",
|
||||||
"Obsolete CSRF token provided"), 406);
|
"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 TRUE;
|
||||||
}
|
}
|
||||||
@@ -116,7 +160,7 @@ class csrf
|
|||||||
// {{{
|
// {{{
|
||||||
{
|
{
|
||||||
$this->checkToken ($tokenFromUser);
|
$this->checkToken ($tokenFromUser);
|
||||||
$_SESSION["domframework"]["csrf"]["csrfStart"] = microtime (TRUE);
|
$_SESSION["domframework"]["csrf"][$tokenFromUser] = microtime (TRUE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|||||||
Reference in New Issue
Block a user