julfiker / csrf-php
PHP 生成 CSRF 令牌并检查 POST 动作的库
v1.1
2018-03-23 09:49 UTC
Requires
- php: >=5.3.3
- symfony/http-foundation: v3.4.6
This package is auto-updated.
Last update: 2024-09-29 04:43:19 UTC
README
生成 CSRF 令牌并在 POST|PULL|DELETE 方法动作中进行检查。这是独立的服务,可用于任何 PHP 应用程序。您可以将它集成到任何 PHP 应用程序中。
安装
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);