Phalcon 安全功能
Phalcon在安全组件的帮助下提供安全功能,用于防止攻击,如密码散列和跨站请求伪造(Cross-Site Request Forgery,CSRF)。
密码散列
密码散列(Hashing)可以定义为将固定长度的位串转换为指定长度且不可逆转的过程,输入字符串中的任何更改都将更改散列数据的值。
散列数据的解密是通过将用户输入的值作为输入并比较相同的散列形式来进行的,通常对于任何基于 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)
这是一种迫使已认证用户执行某些非法操作,接受用户输入的表单很容易受到这种攻击,Phalcon试图保护通过应用程序外的表单发送数据来防止这种攻击。
每个表单中的数据都在令牌生成的帮助下得到保护,生成的令牌是随机的,它与我们发送表单数据的令牌相匹配。
代码:
<?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中引用会话适配器:
/** * Start the session the first time some component request the session service */ $di->setShared('session', function () { $session = new SessionAdapter(); $session->start(); return $session; });