處理密碼(Working with Passwords)

2018-02-24 15:40 更新

處理密碼

注意:本節(jié)內(nèi)容正在開(kāi)發(fā)中。

好的安全策略對(duì)任何應(yīng)用的健康和成功極其重要。不幸的是,許多開(kāi)發(fā)者在遇到安全問(wèn)題時(shí),因?yàn)檎J(rèn)識(shí)不夠或者實(shí)現(xiàn)起來(lái)比較麻煩,都不是很注意細(xì)節(jié)。為了讓你的 Yii 應(yīng)用程序盡可能的安全, Yii 囊括了一些卓越并簡(jiǎn)單易用的安全特性。

密碼的哈希與驗(yàn)證

大部分開(kāi)發(fā)者知道密碼不能以明文形式存儲(chǔ),但是許多開(kāi)發(fā)者仍認(rèn)為使用?md5?或者?sha1?來(lái)哈希化密碼是安全的。一度,使用上述的哈希算法是足夠安全的,但是,現(xiàn)代硬件的發(fā)展使得短時(shí)間內(nèi)暴力破解上述算法生成的哈希串成為可能。

為了即使在最糟糕的情況下(你的應(yīng)用程序被破解了)也能給用戶密碼提供增強(qiáng)的安全性,你需要使用一個(gè)能夠?qū)贡┝ζ平夤舻墓K惴?。目前最好的選擇是?bcrypt。在 PHP 中,你可以通過(guò)?crypt 函數(shù)?生成?bcrypt?哈希。Yii 提供了兩個(gè)幫助函數(shù)以讓使用crypt?來(lái)進(jìn)行安全的哈希密碼生成和驗(yàn)證更加容易。

當(dāng)一個(gè)用戶為第一次使用,提供了一個(gè)密碼時(shí)(比如:注冊(cè)時(shí)),密碼就需要被哈?;?。

$hash = Yii::$app->getSecurity()->generatePasswordHash($password);

哈希串可以被關(guān)聯(lián)到對(duì)應(yīng)的模型屬性,這樣,它可以被存儲(chǔ)到數(shù)據(jù)庫(kù)中以備將來(lái)使用。

當(dāng)一個(gè)用戶嘗試登錄時(shí),表單提交的密碼需要使用之前的存儲(chǔ)的哈希串來(lái)驗(yàn)證:

if (Yii::$app->getSecurity()->validatePassword($password, $hash)) {
    // all good, logging user in
} else {
    // wrong password
}

生成偽隨機(jī)數(shù)

偽隨機(jī)數(shù)據(jù)在許多場(chǎng)景下都非常有用。比如當(dāng)通過(guò)郵件重置密碼時(shí),你需要生成一個(gè)令牌,將其保存到數(shù)據(jù)庫(kù)中,并通過(guò)郵件發(fā)送到終端用戶那里以讓其證明其對(duì)某個(gè)賬號(hào)的所有權(quán)。這個(gè)令牌的唯一性和難猜解性非常重要,否則,就存在攻擊者猜解令牌,并重置用戶的密碼的可能性。

Yii security helper makes generating pseudorandom data simple: Yii 安全助手使得生成偽隨機(jī)數(shù)據(jù)非常簡(jiǎn)單:

$key = Yii::$app->getSecurity()->generateRandomString();

注意,你需要安裝有?openssl?擴(kuò)展,以生成密碼的安全隨機(jī)數(shù)據(jù)。

加密與解密

Yii 提供了方便的幫助函數(shù)來(lái)讓你用一個(gè)安全秘鑰來(lái)加密解密數(shù)據(jù)。數(shù)據(jù)通過(guò)加密函數(shù)進(jìn)行傳輸,這樣只有擁有安全秘鑰的人才能解密。比如,我們需要存儲(chǔ)一些信息到我們的數(shù)據(jù)庫(kù)中,但是,我們需要保證只有擁有安全秘鑰的人才能看到它(即使應(yīng)用的數(shù)據(jù)庫(kù)泄露)

// $data and $secretKey are obtained from the form
$encryptedData = Yii::$app->getSecurity()->encryptByPassword($data, $secretKey);
// store $encryptedData to database

隨后,當(dāng)用戶需要讀取數(shù)據(jù)時(shí):

// $secretKey is obtained from user input, $encryptedData is from the database
$data = Yii::$app->getSecurity()->decryptByPassword($encryptedData, $secretKey);

校驗(yàn)數(shù)據(jù)完整性

有時(shí),你需要驗(yàn)證你的數(shù)據(jù)沒(méi)有第三方篡改或者使用某種方式破壞了。Yii 通過(guò)兩個(gè)幫助函數(shù),提供了一個(gè)簡(jiǎn)單的方式來(lái)進(jìn)行數(shù)據(jù)的完整性校驗(yàn)。

首先,將由安全秘鑰和數(shù)據(jù)生成的哈希串前綴到數(shù)據(jù)上。

// $secretKey our application or user secret, $genuineData obtained from a reliable source
$data = Yii::$app->getSecurity()->hashData($genuineData, $secretKey);

驗(yàn)證數(shù)據(jù)完整性是否被破壞了。

// $secretKey our application or user secret, $data obtained from an unreliable source
$data = Yii::$app->getSecurity()->validateData($data, $secretKey);

todo: XSS 防范, CSRF 防范, Cookie 保護(hù)相關(guān)的內(nèi)容,參考 1.1 文檔

你同樣可以給控制器或者 action 設(shè)置它的?enableCsrfValidation?屬性來(lái)單獨(dú)禁用 CSRF 驗(yàn)證。

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
    }

}

為了給某個(gè)定制的 action 關(guān)閉 CSRF 驗(yàn)證,你可以:

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

參考

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)