elhardoum/nonce-php

快速PHP nonce和CSRF令牌工具

0.12 2018-05-28 20:46 UTC

This package is auto-updated.

Last update: 2024-09-19 08:59:10 UTC


README

快速PHP nonce和CSRF令牌工具,向您的网页表单添加令牌,并使用浏览器cookie或缓存驱动器(或其他任何东西)轻松验证nonce。

Build Status

安装

使用composer

composer require elhardoum/nonce-php

基本用法

首先,导入并初始化nonce实用程序类

// nonce configuration class
$nonceConfig = new \Nonce\Config\Config;

// nonce hash storage, use browser cookies
$nonceStore = new \Nonce\HashStore\Cookie;

// initialize nonce class
$nonceUtil = new \Nonce\Nonce( $nonceConfig, $nonceStore );

然后,根据动作名称创建nonce

// make sure you make this call before starting the output or sending HTTP headers
$nonce = $nonceUtil->create( 'signup-form' );

在这里我们看到我们使用了signup-form作为动作名称,我们稍后可以用它来验证用户请求提供的nonce

让我们在HTML表单中使用这个

<form method="post">
    ....
    ....

    <input type="hidden" name="nonce" value="<?php echo htmlentities($nonce); ?>" />
</form>

现在前端表单应该像这样显示(即添加了nonce字段)

<form method="post">
    ....
    ....

    <input type="hidden" name="nonce" value="7ad510a2296535d545615d" />
</form>

在提交表单时验证此表单的nonce,我们可以将nonce哈希传递给$nonceUtil->verify(string $hash, string $action)方法

if ( isset( $_POST['nonce'] ) && $nonceUtil->verify( $_POST['nonce'], 'signup-form' ) ) {
    # nonce is valid
}

配置

初始化Nonce\Nonce类时,您将配置类作为第一个参数传递

// nonce configuration class
$nonceConfig = new \Nonce\Config\Config;

// initialize nonce class
$nonceUtil = new \Nonce\Nonce( $nonceConfig, new \Nonce\HashStore\Cookie );

您可以通过调用$nonceConfig->setConfig方法或传递自己的配置类(该配置类实现了Nonce\Config\Base接口)来自定义默认配置。

$nonceConfig->setConfig( string $config_name, $config_value );

这允许您覆盖配置类的默认常量。

例如,要更新cookie设置

$nonceConfig->setConfig( 'COOKIE_PATH', '/' );
$nonceConfig->setConfig( 'COOKIE_DOMAIN', 'example.com' );

可用的配置常量

请记住使用$nonceConfig->setConfig来更新以下配置键中的任何一项

// CSRF token cookie name
$nonceConfig::CSRF_COOKIE_NAME = 'CSRF';

CSRF cookie名称。

// CSRF cookie expiration in seconds
$nonceConfig::CSRF_COOKIE_TTL = 7200; // 2 hrs

CSRF令牌附加到浏览器cookie后应过期的秒数。此令牌非常重要,用于生成和验证哈希,因此对每个用户都是唯一的。

$nonceConfig::RANDOM_SALT = 'HI5CTp$94deNBCUqIQx63Z8P$T&^_z`dy';

指定用于生成令牌的随机盐。

$nonceConfig::NONCE_HASH_CHARACTER_LIMIT = 22;

在此处输入字符限制。然后$nonceUtil->create(...)的返回值将是这个字符长度。

$nonceConfig::TOKEN_HASHER_ALGO = 'sha512';

应该传递给hash函数以生成令牌的算法。

$nonceConfig::NONCE_DEFAULT_TTL = 600; // 10 min

nonce生成后应该存活多久?nonce应该有一个有限的生存期,否则您会浪费浏览器cookie或缓存服务器的空间。

在通过$nonceUtil->create(...)方法请求哈希后,过期时间将更新,因此如果哈希5分钟过期,过期时间将在我们重新创建哈希时重置。

$nonceConfig::COOKIE_PATH = '/';

cookie路径,如果使用Nonce在子目录项目中,设置为Web目录名称,或者在根域名上设置为/

注意:即使您使用缓存驱动器来存储哈希,也还需要cookie来存储CSRF令牌。

$nonceConfig::COOKIE_DOMAIN = '127.0.0.1';

当前域名(主机)。

$nonceConfig::HASH_ID_CHARACTRER_LIMIT = 11;

在此处输入字符限制。当您通过cookie存储哈希时,这很重要。

生成的哈希太长,我们需要将其截断以仅获取前几个字符进行标识。当您使用浏览器cookie存储哈希时,这可能会产生较大的请求头,因此我们将尝试存储小的哈希,并在验证nonce时也进行截断。

哈希存储驱动器

nonce标识数据需要临时存储,以便以后验证。

cookie

可以使用浏览器cookies实现简单的临时存储,因此在初始化nonce类时,可以将\Nonce\HashStore\Cookie实例作为第二个参数传递

$nonceUtil = new \Nonce\Nonce( $nonceConfig, new \Nonce\HashStore\Cookie );

请注意,无论您使用的是哪种存储驱动程序,cookies仍然会被用来为请求用户持久化CSRF令牌。

Redis

您还可以通过在初始化nonce类时将\Nonce\HashStore\Redis实例作为第二个参数传递,在您的Redis服务器上临时存储哈希数据

// initialize the class passing an instance of Predis as the first argument
$nonceStore = new \Nonce\HashStore\Redis( new \Predis\Client() );

$nonceUtil = new \Nonce\Nonce( $nonceConfig, $nonceStore );

在实例化\Nonce\HashStore\Redis类时,请确保传递一个\Predis\Client实例。

自定义

您可以通过传递实现\Nonce\HashStore\Store接口的类,使用任何其他临时数据存储方法

<?php

class CustomStore implements \Nonce\HashStore\Store
{
    /**
      * Store a key temporarily
      *
      * @param string $name key to be stored
      * @param string $value value to be stored for the given key
      * @param int $expire_seconds expire the data after X seconds (data TTL)
      * @return bool success/failure
      */

    public function setKey( string $name, string $value, int $expire_seconds=0 ) : bool
    {
        // ...
    }

    /**
      * Get a key from temporary storage
      *
      * @param string $name key to be retrieved
      * @return string value for stored key or empty string on key unavailable
      */

    public function getKey( string $name ) : string
    {
        // ...
    }

    /**
      * Unset a key from temporary storage
      *
      * @param string $name key to be removed
      * @return bool success/failure
      */

    public function deleteKey( string $name ) : bool
    {
        // ...
    }
}