# 安全(Security)
該組件可以幫助開發人員在共同安全方面的一些工作,比如密碼散列和跨站點請求偽造(CSRF)保護。
## 密碼散列(Password Hashing)
將密碼以純文本方式保存是一個糟糕的安全實踐。任何可以訪問數據庫的人可立即訪問所有用戶賬戶,因此能夠從事未經授權的活動。為解決這個問題,許多應用程序使用熟悉的 單向散列方法比如”[md5](http://php.net/manual/en/function.md5.php)“和”[sha1](http://php.net/manual/en/function.sha1.php)“。然而,硬件每天都在發展,變得更快,這些算法在蠻力攻擊面前變得脆弱不堪。這些攻擊也被稱為“彩虹表([rainbow tables](http://en.wikipedia.org/wiki/Rainbow_table))。
為了解決這個問題我們可以使用哈希算法[bcrypt](http://en.wikipedia.org/wiki/Bcrypt)。為什么 bcrypt? 由于其”[Eksblowfish](http://en.wikipedia.org/wiki/Bcrypt#Algorithm)“鍵設置算法,我們可以使密碼加密如同我們想要的”慢”。慢的算法使計算 Hash背后的真實密碼的過程非常困難甚至不可能。這可以在一個很長一段時間內免遭可能的彩虹表攻擊。
這個組件使您能夠以一個簡單的方法使用該算法:
~~~
<?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
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](http://php.net/manual/en/book.openssl.php)。
## 防止跨站點請求偽造攻擊(Cross-Site Request Forgery (CSRF) protection)
這是另一個常見的web站點和應用程序攻擊。如用戶注冊或添加注釋的這類表單就很容易受到這種攻擊。
可以想到的方式防止表單值發送自外部應用程序。為了解決這個問題,我們為每個表單生成一個一次性隨機令牌([random nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)),在會話中添加令牌,然后一旦表單數據提交到 程序之后,將提交的數據中的的令牌和存儲在會中的令牌進行比較,來驗證是否合法。
~~~
<?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
use Phalcon\Mvc\Controller;
class SessionController extends Controller
{
public function loginAction()
{
if ($this->request->isPost()) {
if ($this->security->checkToken()) {
// The token is OK
}
}
}
}
~~~
記得添加一個會話適配器到依賴注入器中,否則令牌檢查是行不通的:
~~~
<?php
$di->setShared(
"session",
function () {
$session = new \Phalcon\Session\Adapter\Files();
$session->start();
return $session;
}
);
~~~
同時也建議為表單添加一個[captcha](http://www.google.com/recaptcha),以完全避免這種攻擊的風險。
## 設置組件(Setting up the component)
該組件自動在服務容器中注冊為“security”,你亦可以重新注冊它并為它設置參數:
~~~
<?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
);
~~~
## Random
The[Phalcon\\Security\\Random](http://docs.iphalcon.cn/api/Phalcon_Security_Random.html)class makes it really easy to generate lots of types of random data.
~~~
<?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);
~~~
## 外部資源(External Resources)
* [V?kuró](http://vokuro.phalconphp.com/), 是一個使用的安全組件避免CSRF和密碼散列的示例應用程序 \[[Github](https://github.com/phalcon/vokuro)\]
- 簡介
- 安裝
- 安裝(installlation)
- XAMPP下的安裝
- WAMP下安裝
- Nginx安裝說明
- Apache安裝說明
- Cherokee 安裝說明
- 使用 PHP 內置 web 服務器
- Phalcon 開發工具
- Linux 系統下使用 Phalcon 開發工具
- Mac OS X 系統下使用 Phalcon 開發工具
- Windows 系統下使用 Phalcon 開發工具
- 教程
- 教程 1:讓我們通過例子來學習
- 教程 2:INVO簡介
- 教程 3: 保護INVO
- 教程4: 使用CRUD
- 教程5: 定制INVO
- 教程 6: V?kuró
- 教程 7:創建簡單的 REST API
- 組件
- 依賴注入與服務定位器
- MVC架構
- 使用控制器
- 使用模型
- 模型關系
- 事件與事件管理器
- Behaviors
- 模型元數據
- 事務管理
- 驗證數據完整性
- Workingwith Models
- Phalcon查詢語言
- 緩存對象關系映射
- 對象文檔映射 ODM
- 使用視圖
- 視圖助手
- 資源文件管理
- Volt 模版引擎
- MVC 應用
- 路由
- 調度控制器
- Micro Applications
- 使用命名空間
- 事件管理器
- Request Environmen
- 返回響應
- Cookie 管理
- 生成 URL 和 路徑
- 閃存消息
- 使用 Session 存儲數據
- 過濾與清理
- 上下文編碼
- 驗證Validation
- 表單_Forms
- 讀取配置
- 分頁 Pagination
- 使用緩存提高性能
- 安全
- 加密與解密 Encryption/Decryption
- 訪問控制列表
- 多語言支持
- 類加載器 Class Autoloader
- 日志記錄_Logging
- 注釋解析器 Annotations Parser
- 命令行應用 Command Line Applications
- Images
- 隊列 Queueing
- 數據庫抽象層
- 國際化
- 數據庫遷移
- 調試應用程序
- 單元測試
- 進階技巧與延伸閱讀
- 提高性能:下一步該做什么?
- Dependency Injection Explained
- Understanding How Phalcon Applications Work
- Api
- Abstract class Phalcon\Acl