-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Magnus Eriksson
committed
Oct 16, 2015
0 parents
commit 84c9489
Showing
7 changed files
with
325 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/vendor | ||
composer.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2015 Magnus Eriksson | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# A small CSRF package for PHP | ||
|
||
Quickly generate and validate tokens to prevent Cross-Site Request Forgery (CSRF) attacks. | ||
|
||
> *__Important:__ This package only helps you with the CSRF tokens. To truly be safe from CSRF, you also need to protect yourself against [Cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) as well.* | ||
|
||
## Install | ||
|
||
Git clone or use composer to download the package with the following command: | ||
``` | ||
composer require maer/csrf 0.* | ||
``` | ||
|
||
## Usage | ||
Include composers autoloader or include the files in the `src/` folder manually. *(start with `CsrfInterface.php`-file)* | ||
|
||
#### Create a new instance #### | ||
|
||
``` | ||
$csrf = new Maer\Security\Csrf\Csrf(); | ||
``` | ||
|
||
*__Important:__ You can create a new instance when ever in your application, but before you make any calls to it, you need to start the session yourself. This package does not make any assumptions on how you manage your sessions (you might use: session_start() or you might use Symfonys Session package etc...)* | ||
|
||
#### Approach 1: Manually add the hidden field #### | ||
``` | ||
<form method="post" action="..."> | ||
<input type="hidden" name="csrftoken" value="<?= $csrf->getToken() ?>" /> | ||
... | ||
</form> | ||
``` | ||
|
||
#### Approach 2: Generate the hidden field #### | ||
``` | ||
<form method="post" action="..."> | ||
<?= $csrf->getTokenField() ?> | ||
... | ||
</form> | ||
``` | ||
|
||
#### Validate | ||
When receiving the post: | ||
``` | ||
if ($csrf->validateToken($_POST['csrftoken'])) { | ||
echo "Yay! It's a valid token!"; | ||
} else { | ||
echo "Nope. That token isn't valid!"; | ||
} | ||
``` | ||
|
||
## More... | ||
Above is the basic usage but there are some more stuff available. I'll update this guide soon... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"name": "maer/csrf", | ||
"description": "A small CSRF package for PHP", | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "Magnus Eriksson", | ||
"email": "mange@reloop.se" | ||
} | ||
], | ||
"autoload": { | ||
"psr-4": { | ||
"Maer\\Security\\Csrf\\": "src/" | ||
} | ||
}, | ||
"minimum-stability": "stable", | ||
"require": { | ||
"php": ">=5.4.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
<?php namespace Maer\Security\Csrf; | ||
/** | ||
* A small CSRF library for generating/verifying CSRF tokens | ||
* | ||
* @author Magnus Eriksson <mange@reloop.se> | ||
* @version 0.1.0 | ||
* @package Maer | ||
* @subpackage Csrf | ||
*/ | ||
class Csrf implements CsrfInterface | ||
{ | ||
/** | ||
* The default token name if user omit the name from the requests | ||
* @var string | ||
*/ | ||
protected $defaultName = 'default'; | ||
|
||
/** | ||
* Collection that holds all tokens from the session | ||
* @var array | ||
*/ | ||
protected $tokens = []; | ||
|
||
/** | ||
* Key name for the session with the token collection | ||
* @var string | ||
*/ | ||
protected $key = 'csrf_tokens'; | ||
|
||
/** | ||
* Have we initialized the library yet? | ||
* @var boolean | ||
*/ | ||
protected $initialized = false; | ||
|
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getToken($name = null) | ||
{ | ||
$this->initialize(); | ||
|
||
$hName = $this->hashName($name); | ||
$token = isset($this->tokens[$hName]) ? $this->tokens[$hName]: null; | ||
|
||
return $token?: $this->regenerateToken($name); | ||
} | ||
|
||
|
||
/** | ||
* Get html markup for a hidden input CSRF field | ||
* | ||
* @param string $name If omitted, the default name will be used | ||
* @return string Html markup | ||
*/ | ||
public function getTokenField($name = null) | ||
{ | ||
$token = $this->getToken(); | ||
return '<input type="hidden" name="csrftoken" value="' . $token . '" />'; | ||
} | ||
|
||
|
||
/** | ||
* Validate a token | ||
* | ||
* @param string $userToken The token to validate | ||
* @param string $name If omitted, the default name will be used | ||
* @return bool | ||
*/ | ||
public function validateToken($userToken, $name = null) | ||
{ | ||
$token = $this->getToken($name); | ||
return !is_null($userToken) && $token === $userToken; | ||
} | ||
|
||
|
||
/** | ||
* Regenerate a CSRF token | ||
* | ||
* @param string $name If omitted, the default token will be regenerated | ||
*/ | ||
public function regenerateToken($name = null) | ||
{ | ||
$this->initialize(); | ||
|
||
$name = $this->hashName($name); | ||
$this->tokens[$name] = base64_encode(openssl_random_pseudo_bytes(64)); | ||
|
||
if (!isset($_SESSION[$this->key]) || !is_array($_SESSION[$this->key])) { | ||
$_SESSION[$this->key] = []; | ||
} | ||
|
||
$_SESSION[$this->key][$name] = $this->tokens[$name]; | ||
|
||
return $this->tokens[$name]; | ||
} | ||
|
||
|
||
/** | ||
* Reset/delete all tokens | ||
*/ | ||
public function resetAll() | ||
{ | ||
$this->initialize(); | ||
|
||
$this->tokens = []; | ||
unset($_SESSION[$this->key]); | ||
} | ||
|
||
|
||
/** | ||
* Get current session tokens, if there are any. | ||
* | ||
* @return void | ||
*/ | ||
protected function initialize() | ||
{ | ||
if ($this->initialized) { | ||
// Already initialized | ||
return true; | ||
} | ||
|
||
if (session_status() !== PHP_SESSION_NONE) { | ||
|
||
if (isset($_SESSION[$this->key]) && is_array($_SESSION[$this->key])) { | ||
// Get the token collection from the session, if we got any | ||
$this->tokens = $_SESSION[$this->key]; | ||
} | ||
|
||
$this->initialized = true; | ||
|
||
} else { | ||
|
||
throw new CsrfSessionException('A session must be started before the Csrf library can be used'); | ||
|
||
} | ||
} | ||
|
||
|
||
/** | ||
* Normalize and MD5 hash the name (this is not for security reasons | ||
* but rather to remove weird characters in the name) | ||
* | ||
* @param string $name If omitted, the default token will be regenerated | ||
* @return string | ||
*/ | ||
protected function hashName($name = null) | ||
{ | ||
$name = strtolower($name); | ||
return md5($name?: $this->defaultName); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?php namespace Maer\Security\Csrf; | ||
/** | ||
* A small CSRF library for generating/verifying CSRF tokens | ||
* | ||
* @author Magnus Eriksson <mange@reloop.se> | ||
* @version 0.1.0 | ||
* @package Maer | ||
* @subpackage Csrf | ||
*/ | ||
interface CsrfInterface | ||
{ | ||
|
||
/** | ||
* Get a CSRF token | ||
* | ||
* @param string $name If omitted, the default name will be used | ||
* @return string | ||
*/ | ||
public function getToken($name = null); | ||
|
||
|
||
/** | ||
* Get html markup for a hidden input CSRF field | ||
* | ||
* @param string $name If omitted, the default name will be used | ||
* @return string Html markup | ||
*/ | ||
public function getTokenField($name = null); | ||
|
||
|
||
/** | ||
* Validate a token | ||
* | ||
* @param string $userToken The token to validate | ||
* @param string $name If omitted, the default name will be used | ||
* @return bool | ||
*/ | ||
public function validateToken($userToken, $name = null); | ||
|
||
|
||
/** | ||
* Regenerate a CSRF token | ||
* | ||
* @param string $name If omitted, the default token will be regenerated | ||
*/ | ||
public function regenerateToken($name = null); | ||
|
||
|
||
/** | ||
* Reset/delete all tokens | ||
*/ | ||
public function resetAll(); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php namespace Maer\Security\Csrf; | ||
/** | ||
* A small CSRF library for generating/verifying CSRF tokens | ||
* | ||
* @author Magnus Eriksson <mange@reloop.se> | ||
* @version 0.1.0 | ||
* @package Maer | ||
* @subpackage Csrf | ||
*/ | ||
class CsrfSessionException extends \Exception | ||
{ | ||
|
||
} |