🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 安全 该组件帮助开发人员执行常见的安全任务,例如密码散列和跨站请求伪造保护([CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery))。 ## Password Hashing 以纯文本格式存储密码是一种糟糕的安全措施。有权访问数据库的任何人都可以立即访问所有用户帐户,从而可以进行未经授权的活动。为了解决这个问题,许多应用程序使用熟悉的单向散列方法'[md5](http://php.net/manual/en/function.md5.php)'和'[sha1](http://php.net/manual/en/function.sha1.php)'。但是,硬件每天都会发展变得越来越快,这些算法越来越容易受到强力攻击。这些攻击也称为[彩虹表](http://en.wikipedia.org/wiki/Rainbow_table)。 为了解决这个问题,我们可以使用哈希算法作为[bcrypt](http://en.wikipedia.org/wiki/Bcrypt)。为什么要加密?由于其'[Eksblowfish](http://en.wikipedia.org/wiki/Bcrypt#Algorithm)'密钥设置算法,我们可以根据需要将密码加密设置为“慢”。慢速算法使得计算哈希背后的真实密码的过程非常困难,如果不是不可能的话。这将使用彩虹表保护您长时间免受可能的攻击。 该组件使您能够以一种简单的方式使用此算法: ```php <?php use Phalcon\Mvc\Controller; class UsersController extends Controller { public function registerAction() { $user = new Users(); $login = $this->request->getPost('login'); $password = $this->request->getPost('password'); $user->login = $login; // Store the password hashed $user->password = $this->security->hash($password); $user->save(); } } ``` 我们使用默认工作因子保存了密码哈希值。较高的工作因素会使密码不易受到攻击,因为加密速度会很慢。我们可以检查密码是否正确如下: ```php <?php use Phalcon\Mvc\Controller; class SessionController extends Controller { public function loginAction() { $login = $this->request->getPost('login'); $password = $this->request->getPost('password'); $user = Users::findFirstByLogin($login); if ($user) { if ($this->security->checkHash($password, $user->password)) { // The password is valid } } else { // To protect against timing attacks. Regardless of whether a user // exists or not, the script will take roughly the same amount as // it will always be computing a hash. $this->security->hash(rand()); } // The validation has failed } } ``` 使用伪随机字节生成salt,其PHP函数为[openssl_random_pseudo_bytes](http://php.net/manual/en/function.openssl-random-pseudo-bytes.php),因此需要加载openssl扩展。 ## 跨站请求伪造(CSRF)保护 这是针对网站和应用程序的另一种常见攻击。用于执行用户注册或添加注释等任务的表单容易受到此攻击。 我们的想法是防止在我们的应用程序之外发送表单值。为了解决这个问题,我们在每个表单中生成一个随机的[随机数](http://en.wikipedia.org/wiki/Cryptographic_nonce)(令牌),在会话中添加令牌,然后在表单通过将会话中存储的令牌与会话中提交的令牌进行比较后将数据发布回应用程序时验证令牌。形成: ```php <?php echo Tag::form('session/login') ?> <!-- Login and password inputs ... --> <input type='hidden' name='<?php echo $this->security->getTokenKey() ?>' value='<?php echo $this->security->getToken() ?>'/> </form> ``` 然后在控制器的操作中,您可以检查CSRF令牌是否有效: ```php <?php use Phalcon\Mvc\Controller; class SessionController extends Controller { public function loginAction() { if ($this->request->isPost()) { if ($this->security->checkToken()) { // The token is OK } } } } ``` 请记住将会话适配器添加到Dependency Injector,否则令牌检查将不起作用: ```php <?php $di->setShared( 'session', function () { $session = new \Phalcon\Session\Adapter\Files(); $session->start(); return $session; } ); ``` 建议在表单中添加[验证码](http://www.google.com/recaptcha)以完全避免此攻击的风险。 ## 设置组件 此组件作为`security`自动注册在服务容器中,您可以重新注册它以设置其选项: ```php <?php use Phalcon\Security; $di->set( 'security', function () { $security = new Security(); // Set the password hashing factor to 12 rounds $security->setWorkFactor(12); return $security; }, true ); ``` ## 随机数 `Phalcon\Security\Random`类使得生成许多类型的随机数据变得非常容易。 ```php <?php use Phalcon\Security\Random; $random = new Random(); // ... $bytes = $random->bytes(); // Generate a random hex string of length $len. $hex = $random->hex($len); // Generate a random base64 string of length $len. $base64 = $random->base64($len); // Generate a random URL-safe base64 string of length $len. $base64Safe = $random->base64Safe($len); // Generate a UUID (version 4). // See https://en.wikipedia.org/wiki/Universally_unique_identifier $uuid = $random->uuid(); // Generate a random integer between 0 and $n. $number = $random->number($n); ``` ## 外部资源 * [Vökuró](https://vokuro.phalconphp.com)是一个示例应用程序,它使用安全组件来避免CSRF和密码散列,[Github](https://github.com/phalcon/vokuro)