# 處理密碼
> 注意:本節內容正在開發中。
好的安全策略對任何應用的健康和成功極其重要。不幸的是,許多開發者在遇到安全問題時,因為認識不夠或者實現起來比較麻煩,都不是很注意細節。為了讓你的 Yii 應用程序盡可能的安全, Yii 囊括了一些卓越并簡單易用的安全特性。
## 密碼的哈希與驗證
大部分開發者知道密碼不能以明文形式存儲,但是許多開發者仍認為使用?`md5`?或者?`sha1`?來哈希化密碼是安全的。一度,使用上述的哈希算法是足夠安全的,但是,現代硬件的發展使得短時間內暴力破解上述算法生成的哈希串成為可能。
為了即使在最糟糕的情況下(你的應用程序被破解了)也能給用戶密碼提供增強的安全性,你需要使用一個能夠對抗暴力破解攻擊的哈希算法。目前最好的選擇是?`bcrypt`。在 PHP 中,你可以通過?[crypt 函數](http://php.net/manual/en/function.crypt.php)?生成?`bcrypt`?哈希。Yii 提供了兩個幫助函數以讓使用`crypt`?來進行安全的哈希密碼生成和驗證更加容易。
當一個用戶為第一次使用,提供了一個密碼時(比如:注冊時),密碼就需要被哈希化。
~~~
$hash = Yii::$app->getSecurity()->generatePasswordHash($password);
~~~
哈希串可以被關聯到對應的模型屬性,這樣,它可以被存儲到數據庫中以備將來使用。
當一個用戶嘗試登錄時,表單提交的密碼需要使用之前的存儲的哈希串來驗證:
~~~
if (Yii::$app->getSecurity()->validatePassword($password, $hash)) {
// all good, logging user in
} else {
// wrong password
}
~~~
## 生成偽隨機數
偽隨機數據在許多場景下都非常有用。比如當通過郵件重置密碼時,你需要生成一個令牌,將其保存到數據庫中,并通過郵件發送到終端用戶那里以讓其證明其對某個賬號的所有權。這個令牌的唯一性和難猜解性非常重要,否則,就存在攻擊者猜解令牌,并重置用戶的密碼的可能性。
Yii security helper makes generating pseudorandom data simple: Yii 安全助手使得生成偽隨機數據非常簡單:
~~~
$key = Yii::$app->getSecurity()->generateRandomString();
~~~
注意,你需要安裝有?`openssl`?擴展,以生成密碼的安全隨機數據。
## 加密與解密
Yii 提供了方便的幫助函數來讓你用一個安全秘鑰來加密解密數據。數據通過加密函數進行傳輸,這樣只有擁有安全秘鑰的人才能解密。比如,我們需要存儲一些信息到我們的數據庫中,但是,我們需要保證只有擁有安全秘鑰的人才能看到它(即使應用的數據庫泄露)
~~~
// $data and $secretKey are obtained from the form
$encryptedData = Yii::$app->getSecurity()->encryptByPassword($data, $secretKey);
// store $encryptedData to database
~~~
隨后,當用戶需要讀取數據時:
~~~
// $secretKey is obtained from user input, $encryptedData is from the database
$data = Yii::$app->getSecurity()->decryptByPassword($encryptedData, $secretKey);
~~~
## 校驗數據完整性
有時,你需要驗證你的數據沒有第三方篡改或者使用某種方式破壞了。Yii 通過兩個幫助函數,提供了一個簡單的方式來進行數據的完整性校驗。
首先,將由安全秘鑰和數據生成的哈希串前綴到數據上。
~~~
// $secretKey our application or user secret, $genuineData obtained from a reliable source
$data = Yii::$app->getSecurity()->hashData($genuineData, $secretKey);
~~~
驗證數據完整性是否被破壞了。
~~~
// $secretKey our application or user secret, $data obtained from an unreliable source
$data = Yii::$app->getSecurity()->validateData($data, $secretKey);
~~~
todo: XSS 防范, CSRF 防范, Cookie 保護相關的內容,參考 1.1 文檔
你同樣可以給控制器或者 action 設置它的?`enableCsrfValidation`?屬性來單獨禁用 CSRF 驗證。
~~~
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public $enableCsrfValidation = false;
public function actionIndex()
{
// CSRF validation will not be applied to this and other actions
}
}
~~~
為了給某個定制的 action 關閉 CSRF 驗證,你可以:
~~~
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function beforeAction($action)
{
// ...set `$this->enableCsrfValidation` here based on some conditions...
// call parent method that will check CSRF if such property is true.
return parent::beforeAction($action);
}
}
~~~
## 安全 Cookie
* validation
* httpOnly is default
## 參考
* [Views security](http://www.yiichina.com/doc/guide/2.0/structure-views#security)
- 介紹(Introduction)
- 關于 Yii(About Yii)
- 從 Yii 1.1 升級(Upgrading from Version 1.1)
- 入門(Getting Started)
- 安裝 Yii(Installing Yii)
- 運行應用(Running Applications)
- 第一次問候(Saying Hello)
- 使用 Forms(Working with Forms)
- 玩轉 Databases(Working with Databases)
- 用 Gii 生成代碼(Generating Code with Gii)
- 更上一層樓(Looking Ahead)
- 應用結構(Application Structure)
- 結構概述(Overview)
- 入口腳本(Entry Scripts)
- 應用(Applications)
- 應用組件(Application Components)
- 控制器(Controllers)
- 模型(Models)
- 視圖(Views)
- 模塊(Modules)
- 過濾器(Filters)
- 小部件(Widgets)
- 前端資源(Assets)
- 擴展(Extensions)
- 請求處理(Handling Requests)
- 運行概述(Overview)
- 引導(Bootstrapping)
- 路由引導與創建 URL(Routing and URL Creation)
- 請求(Requests)
- 響應(Responses)
- Sessions and Cookies
- 錯誤處理(Handling Errors)
- 日志(Logging)
- 關鍵概念(Key Concepts)
- 組件(Components)
- 屬性(Properties)
- 事件(Events)
- 行為(Behaviors)
- 配置(Configurations)
- 別名(Aliases)
- 類自動加載(Class Autoloading)
- 服務定位器(Service Locator)
- 依賴注入容器(Dependency Injection Container)
- 配合數據庫工作(Working with Databases)
- 數據庫訪問(Data Access Objects): 數據庫連接、基本查詢、事務和模式操作
- 查詢生成器(Query Builder): 使用簡單抽象層查詢數據庫
- 活動記錄(Active Record): 活動記錄對象關系映射(ORM),檢索和操作記錄、定義關聯關系
- 數據庫遷移(Migrations): 在團體開發中對你的數據庫使用版本控制
- Sphinx
- Redis
- MongoDB
- ElasticSearch
- 接收用戶數據(Getting Data from Users)
- 創建表單(Creating Forms)
- 輸入驗證(Validating Input)
- 文件上傳(Uploading Files)
- 收集列表輸入(Collecting Tabular Input)
- 多模型同時輸入(Getting Data for Multiple Models)
- 顯示數據(Displaying Data)
- 格式化輸出數據(Data Formatting)
- 分頁(Pagination)
- 排序(Sorting)
- 數據提供器(Data Providers)
- 數據小部件(Data Widgets)
- 操作客戶端腳本(Working with Client Scripts)
- 主題(Theming)
- 安全(Security)
- 認證(Authentication)
- 授權(Authorization)
- 處理密碼(Working with Passwords)
- 客戶端認證(Auth Clients)
- 安全領域的最佳實踐(Best Practices)
- 緩存(Caching)
- 概述(Overview)
- 數據緩存(Data Caching)
- 片段緩存(Fragment Caching)
- 分頁緩存(Page Caching)
- HTTP 緩存(HTTP Caching)
- RESTful Web 服務
- 快速入門(Quick Start)
- 資源(Resources)
- 控制器(Controllers)
- 路由(Routing)
- 格式化響應(Response Formatting)
- 授權驗證(Authentication)
- 速率限制(Rate Limiting)
- 版本化(Versioning)
- 錯誤處理(Error Handling)
- 開發工具(Development Tools)
- 調試工具欄和調試器(Debug Toolbar and Debugger)
- 使用 Gii 生成代碼(Generating Code using Gii)
- TBD 生成 API 文檔(Generating API Documentation)
- 測試(Testing)
- 概述(Overview)
- 搭建測試環境(Testing environment setup)
- 單元測試(Unit Tests)
- 功能測試(Functional Tests)
- 驗收測試(Acceptance Tests)
- 測試夾具(Fixtures)
- 高級專題(Special Topics)
- 高級應用模版(Advanced Project Template)
- 從頭構建自定義模版(Building Application from Scratch)
- 控制臺命令(Console Commands)
- 核心驗證器(Core Validators)
- 國際化(Internationalization)
- 收發郵件(Mailing)
- 性能優化(Performance Tuning)
- 共享主機環境(Shared Hosting Environment)
- 模板引擎(Template Engines)
- 集成第三方代碼(Working with Third-Party Code)
- 小部件(Widgets)
- Bootstrap 小部件(Bootstrap Widgets)
- jQuery UI 小部件(jQuery UI Widgets)
- 助手類(Helpers)
- 助手一覽(Overview)
- Array 助手(ArrayHelper)
- Html 助手(Html)
- Url 助手(Url)