Phalcon - 安全功能
Phalcon 借助安全组件提供安全功能,可帮助执行某些任务,如密码哈希处理和跨站点请求伪造 (CSRF)。
哈希处理密码
哈希处理可定义为将固定长度的位字符串转换为指定长度的过程,且该过程不可逆。输入字符串的任何更改都会更改哈希数据的值。
哈希数据的解密是通过将用户输入的值作为输入并比较其哈希形式来进行的。通常对于任何基于 Web 的应用程序,将密码存储为纯文本是一种不好的做法。它很容易受到第三方攻击,因为有权访问数据库的人可以轻松获取任何用户的密码。
Phalcon 提供了一种简单的方法来以加密形式存储密码,该加密形式遵循 md5、base64 或 sh1 等算法。
如前几章所示,我们为博客创建了一个项目。登录屏幕接受用户的用户名和密码输入。要从用户那里接收密码并以特定形式解密,请使用以下代码片段。
然后将解密的密码与从用户那里接受的输入密码进行匹配。如果值匹配,则用户可以成功登录到 Web 应用程序,否则将显示错误消息。
<?php class UsersController extends Phalcon\Mvc\Controller { public function indexAction() { } public function registerUser() { $user = new Users(); $login = $this->request->getPost("login"); $password = $this->request->getPost("password"); $user->login = $login; // 存储哈希密码 $user->password = $this->security->sh1($password); $user->save(); } public function loginAction() { if ($this->request->isPost()) { $user = Users::findFirst(array( 'login = :login: and password = :password:', 'bind' => array( 'login' => $this->request->getPost("login"), 'password' => sha1($this->request->getPost("password")) ) )); if ($user === false) { $this->flash->error("Incorrect credentials"); return $this->dispatcher->forward(array( 'controller' => 'users', 'action' => 'index' )); } $this->session->set('auth', $user->id); $this->flash->success("You've been successfully logged in"); } return $this->dispatcher->forward(array( 'controller' => 'posts', 'action' => 'index' )); } public function logoutAction() { $this->session->remove('auth'); return $this->dispatcher->forward(array( 'controller' => 'posts', 'action' => 'index' )); } }
数据库中存储的密码采用 sh1 算法的加密格式。
一旦用户输入了正确的用户名和密码,用户就可以访问系统,否则将显示错误消息作为验证。
跨站点请求伪造 (CSRF)
这是一种迫使经过身份验证的 Web 应用程序用户执行某些不必要的操作的攻击。接受用户输入的表单容易受到此攻击。Phalcon 试图通过保护通过应用程序外部的表单发送的数据来防止此攻击。
每个表单中的数据都通过令牌生成来保护。生成的令牌是随机的,它与我们向其发送表单数据的令牌相匹配(主要通过 POST 方法在 Web 应用程序之外发送)。
代码:
<?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>
注意 − 在发送表单令牌时使用会话适配器非常重要,因为所有数据都将在会话中维护。
使用以下代码在 services.php 中包含会话适配器。
/** * 当某个组件第一次请求会话服务时启动会话 */ $di->setShared('session', function () { $session = new SessionAdapter(); $session->start(); return $session; });