julfiker/csrf-php

PHP 生成 CSRF 令牌并检查 POST 动作的库

安装: 19

依赖项: 0

建议者: 0

安全性: 0

星标: 3

关注者: 2

分支: 0

开放问题: 0

类型:服务

v1.1 2018-03-23 09:49 UTC

This package is auto-updated.

Last update: 2024-09-29 04:43:19 UTC


README

生成 CSRF 令牌并在 POST|PULL|DELETE 方法动作中进行检查。这是独立的服务,可用于任何 PHP 应用程序。您可以将它集成到任何 PHP 应用程序中。
Scrutinizer Code Quality Build Status Code Intelligence Status

安装

composer require julfiker/csrf-php

只需运行 composer require 命令并指定包名。这假设您已安装 composer 并在路径中可用,名称为 composer。有关安装 composer 的说明,请参阅 https://composer.php.ac.cn/doc/00-intro.md

如何在纯 PHP 应用程序中使用

require_once __DIR__."/vendor/autoload.php";
use Julfiker\Service\CsrfManager as Csrf;
$csrf = new Csrf();
$csrf->setExpiredAt(10); //10 minutes; But default it has 30 minutes
$token = $csrf->getCSRFToken();
$tokenFieldName = $csrf->getTokenFieldName();
<!-- view html template page -->
<form action="post.php" method="post">
    <label>Subscribes email</label>
    <input type="text" name="email" />
    <input type="hidden" value="<?php echo $token?>" name="<?php echo $tokenFieldName?>" />
    <button type="submit">Submit</button>
</form>

在 POST 动作中检查令牌

require_once __DIR__."/vendor/autoload.php";
use Julfiker\Service\CsrfManager as Csrf;


$csrf = new Csrf();
if (!$csrf->isValidToken()) { //Is not valid token
    echo "Invalid token!";
    exit;
}
echo "Token was valid and saving the information";

如何在 zendframework 1.* 中使用

有多种方法可以将 CSRF 令牌验证集成到控制器动作中

选项 1:您可以使用自定义动作助手在特定控制器动作中检查 CSRF 令牌
选项 2:插件,用于在常规的每个 POST 动作方法中检查 CSRF 令牌。
示例动作助手

/**
 * Action helper checking csrf from action, it can be used in controller action like
 *
 * $this->_helper->csrf->validateToken()->ifInvalid()->gotoReferer();
 * OR
 * $this->_helper->csrf->validateToken()->ifInvalid()->gotoUrl('url_str');
 * OR
 * $csrf = $this->_helper->csrf->validateToken();
 * if ($csrf->isInvalidToken())
 *  $csrf->gotoUrl('url_string');
 *
 * @author: Julfiker <mail.julfiker@gmail.com>
 */
class ProjectNameSpace_Zend_Controller_Action_Helper_Csrf extends  Zend_Controller_Action_Helper_Redirector
{
    /** @var \Julfiker\Service\CsrfManager  */
    protected $csrfManager;

    /** @var bool  */
    protected $isValidToken = false;

    /** @var \Zend_Controller_Action_Helper_FlashMessenger  */
    protected $flashMessenger;

    public function __construct() {
        //Dependency injecting
        $this->csrfManager = new \Julfiker\Service\CsrfManager();
        $this->flashMessenger =  \Zend_Controller_Action_HelperBroker::getStaticHelper('FlashMessenger');
    }

    /**
     * Checking csrf token valid or not
     * @return $this
     */
    public function validateToken() {
        $this->isValidToken = $this->getCsrfManager()->isValidToken();
        return $this;
    }

    /**
     * @return $this
     */
    public function ifInvalid() {
        return $this;
    }

    /**
     * Redirecting to referer url
     */
    public function goToReferer() {
         if ($this->isInvalidToken()) {
             $this->flashMessenger->addMessage(array('error' => "Invalid token!"));
             return $this->gotoUrl($_SERVER['HTTP_REFERER']);
         }

        return $this->isValidToken;
    }

    /**
     * Redirecting to specific url
     * @param string $url
     * @param array $options
     * @return redirect|bool
     */
    public function gotoUrl($url, array $options = array()) {
        if ($this->isInvalidToken()) {
            return parent::gotoUrl($url, $options);
        }
        return $this->isValidToken;
    }

    /**
     * Get Csrf manager instance
     */
    public function getCsrfManager() {
        return $this->csrfManager;
    }

    /**
     * @return bool
     */
    public function isValidToken() {
        return $this->isValidToken;
    }

    /**
     * @return bool
     */
    public function isInvalidToken() {
        return !$this->isValidToken;
    }
}

如何在控制器中使用动作助手

使用动作助手的控制器动作示例

//Checking csrf protection
$this->_helper->csrf->validateToken()
    ->ifInvalid()
    ->gotoReferer();
//Or
$csrf = $this->_helper->csrf->validateToken(); 
if ($csrf->isInvalidToken())
$csrf->gotoUrl(‘url_string’);

然而,如果没有动作助手,您可以直接使用服务来检查 CSRF 令牌,如下所示

$csrf = new \Julfiker\Service\CsrfManager();
if (!$csrf->isValidToken()) {
    echo "Invalid token!";
    exit;
}

另一种在所有动作中一般检查令牌的方法。
您需要创建一个控制器插件

示例插件代码*

/**
 * Class ProjectNameSpace_Zend_Controller_Plugin_Csrf
 */
class ProjectNameSpace_Zend_Controller_Plugin_Csrf extends Zend_Controller_Plugin_Abstract
{
    /**
     * @param Zend_Controller_Request_Abstract $request
     */
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
       if ($request->isPost() || $request->isPut() || $request->isDelete()) {
         $csrf = new \Julfiker\Service\CsrfManager();
            if (!$csrf->isValidToken()) {
                //Redirect logic
                //Set flash error message here
                if ($referer = $request->getHeader('referer')) {                    
                    $this->_response->setRedirect($referer); 
                }
                else {
                    $this->_response->setRedirect("/"); 
                }
            }
       }
    }
}

注意:您需要在 application.ini 中注册插件。或者通过前端控制器。

在表单上渲染带有隐藏输入元素的 HTML 令牌

我建议使用视图助手来完成此操作。

示例视图助手

/**
 * Csrf token view helper used to render token
 *
 * @author: Julfiker <mail.julfiker@gmail.com>
 */
class ProjectNameSpace_Zend_View_Helper_CsrfToken extends Zend_View_Helper_Abstract
{
    /** @var  \Julfiker\Service\CsrfManager */
    private $csrfManager;

    /**
     * View to helper to render csrf token
     */
    public function csrfToken() {
        $this->csrfManager = new \Julfiker\Service\CsrfManager();
        //$this->csrfManager->setExpiredAt(30); //Set expired at, Default 30 MINUTES
        return $this;
    }

    /**
     * Render token field in html format
     * in the template or view page
     * @return string as html
     */
    public function render() {
       return "<input type='hidden' name='".$this->getCsrfManager()->getTokenFieldName()."' value='".$this->getCsrfManager()->getCSRFToken()."' />";
    }

    /**
     * @return \managers\CSRFManager
     */
    public function getCsrfManager() {
        return $this->csrfManager;
    }

    /**
     * Get token element for the form object, get specific element object with token value
     * @return \Zend_Form_Element_Hidden;
     */
    public function getElement() {
        $token = new Zend_Form_Element_Hidden($this->getCsrfManager()->getTokenFieldName());
        $token->setValue($this->csrfManager->getCSRFToken());
        return $token;
    }
}

通过示例视图助手代码在 HTML 视图中渲染令牌

如果您使用了原始 HTML 表单,则可以使用以下代码来渲染令牌隐藏字段

<?php echo $this->csrfToken()->render(); ?>

如果您使用 zend 表单来渲染表单,则可以使用以下示例代码将令牌添加到表单中

$csrfToken = $this->getView()->csrfToken()->getElement(); 
$this->addElement($csrfToken);