security-passwords.md 5.06 KB
Newer Older
1 2 3
Security
========

4
> Note: This section is under development.
Qiang Xue committed
5

Aris Karageorgos committed
6
Good security is vital to the health and success of any application. Unfortunately, many developers cut corners when it comes to security, either due to a lack of understanding or because implementation is too much of a hurdle. To make your Yii powered application as secure as possible, Yii has included several excellent and easy to use security features.
7

8

9
Hashing and verifying passwords
10
-------------------------------
11

Aris Karageorgos committed
12
Most developers know that passwords cannot be stored in plain text, but many developers believe it's still safe to hash passwords using `md5` or `sha1`. There was a time when using the aforementioned hashing algorithms was sufficient, but modern hardware makes it possible to reverse such hashes very quickly using brute force attacks.
13

Aris Karageorgos committed
14
In order to provide increased security for user passwords, even in the worst case scenario (your application is breached), you need to use a hashing algorithm that is resilient against brute force attacks. The best current choice is `bcrypt`. In PHP, you can create a `bcrypt` hash  using the [crypt function](http://php.net/manual/en/function.crypt.php). Yii provides two helper functions which make using `crypt` to securely generate and verify hashes easier.
15

Larry Ullman committed
16
When a user provides a password for the first time (e.g., upon registration), the password needs to be hashed:
17

Aris Karageorgos committed
18

19
```php
Aris Karageorgos committed
20
$hash = \yii\helpers\Security::generatePasswordHash($password);
21 22
```

Aris Karageorgos committed
23 24 25
The hash can then be associated with the corresponding model attribute, so it can be stored in the database for later use.

When a user attempts to log in, the submitted password must be verified against the previously hashed and stored password:
26 27 28


```php
Aris Karageorgos committed
29
use yii\helpers\Security;
Larry Ullman committed
30
if (Security::validatePassword($password, $hash)) {
31
    // all good, logging user in
Larry Ullman committed
32
} else {
33
    // wrong password
34 35 36
}
```

Aris Karageorgos committed
37
Generating Pseudorandom data
38 39
-----------

Aris Karageorgos committed
40
Pseudorandom data is useful in many situations. For example when resetting a password via email you need to generate a token, save it to the database, and send it via email to end user which in turn will allow them to prove ownership of that account. It is very important that this token be unique and hard to guess, else there is a possibility and attacker can predict the token's value and reset the user's password.
Aris Karageorgos committed
41 42

Yii security helper makes generating pseudorandom data simple:
43 44 45 46 47 48


```php
$key = \yii\helpers\Security::generateRandomKey();
```

Aris Karageorgos committed
49 50
Note that you need to have the `openssl` extension installed in order to generate cryptographically secure random data.

51 52 53
Encryption and decryption
-------------------------

Aris Karageorgos committed
54 55
Yii provides convenient helper functions that allow you to encrypt/decrypt data using a secret key. The data is passed through and encryption function so that only the person which has the secret key will be able to decrypt it.
For example, we need to store some information in our database but we need to make sure only the user which has the secret key can view it (even if the application database is compromised):
56 57 58


```php
Aris Karageorgos committed
59
// $data and $secretKey are obtained from the form
Aris Karageorgos committed
60
$encryptedData = \yii\helpers\Security::encrypt($data, $secretKey);
61 62 63
// store $encryptedData to database
```

Aris Karageorgos committed
64
Subsequently when user wants to read the data:
65 66

```php
Aris Karageorgos committed
67
// $secretKey is obtained from user input, $encryptedData is from the database
Aris Karageorgos committed
68
$data = \yii\helpers\Security::decrypt($encryptedData, $secretKey);
69 70
```

71
Confirming data integrity
72 73
--------------------------------

Aris Karageorgos committed
74 75 76 77
There are situations in which you need to verify that your data hasn't been tampered with by a third party or even corrupted in some way. Yii provides an easy way to confirm data integrity in the form of two helper functions.  

Prefix the data with a hash generated from the secret key and data

78

Aris Karageorgos committed
79 80
```php
// $secretKey our application or user secret, $genuineData obtained from a reliable source 
Aris Karageorgos committed
81
$data = \yii\helpers\Security::hashData($genuineData, $secretKey);
Aris Karageorgos committed
82 83 84 85 86 87
```

Checks if the data integrity has been compromised

```php
// $secretKey our application or user secret, $data obtained from an unreliable source 
Aris Karageorgos committed
88
$data = \yii\helpers\Security::validateData($data, $secretKey);
Aris Karageorgos committed
89
```
90 91


92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
todo: XSS prevention, CSRF prevention, cookie protection, refer to 1.1 guide

You also can disable CSRF validation per controller and/or action, by setting its property:

```php
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
    }

}
```

To disable CSRF validation per custom actions you can do:

```php
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);
    }
}
```

131 132 133 134
Securing Cookies
----------------

- validation
135
- httpOnly is default
136 137 138 139 140 141

See also
--------

- [Views security](view.md#security)