在Yii2的basic版本中默认是从一个数组验证用户名和密码,如何改为从数据表中查询验证呢?且数据库的密码要为哈希加密密码验证?
下面我们就一步一步解析Yii2的登录过程。
表结构如下:
<span>CREATE</span> <span>TABLE</span> `<span>user</span><span>` ( `id` </span><span>int</span>(<span>11</span>) <span>NOT</span> <span>NULL</span><span> AUTO_INCREMENT, `pid` </span><span>int</span>(<span>11</span>) <span>NOT</span> <span>NULL</span> <span>DEFAULT</span> <span>'</span><span>0</span><span>'</span> COMMENT <span>'</span><span>父id</span><span>'</span><span>, `username` </span><span>char</span>(<span>70</span>) <span>NOT</span> <span>NULL</span> COMMENT <span>'</span><span>用户名</span><span>'</span><span>, `password` </span><span>char</span>(<span>70</span>) <span>NOT</span> <span>NULL</span> COMMENT <span>'</span><span>密码</span><span>'</span><span>, `type` </span><span>tinyint</span>(<span>4</span>) <span>NOT</span> <span>NULL</span> <span>DEFAULT</span> <span>'</span><span>4</span><span>'</span> COMMENT <span>'</span><span>类型(1:总店,2:门店,3:管理员)</span><span>'</span><span>, `created_time` </span><span>int</span>(<span>11</span>) <span>NOT</span> <span>NULL</span> COMMENT <span>'</span><span>注册时间</span><span>'</span><span>, `updated_time` </span><span>int</span>(<span>11</span>) <span>NOT</span> <span>NULL</span> COMMENT <span>'</span><span>修改时间</span><span>'</span><span>, `status` </span><span>tinyint</span>(<span>4</span>) <span>NOT</span> <span>NULL</span> <span>DEFAULT</span> <span>'</span><span>1</span><span>'</span> COMMENT <span>'</span><span>封禁状态,0禁止1正常</span><span>'</span><span>, `login_ip` </span><span>char</span>(<span>20</span>) <span>NOT</span> <span>NULL</span> COMMENT <span>'</span><span>登录ip</span><span>'</span><span>, `login_time` </span><span>int</span>(<span>11</span>) <span>NOT</span> <span>NULL</span> COMMENT <span>'</span><span>上一次登录时间</span><span>'</span><span>, `login_count` </span><span>int</span>(<span>10</span>) <span>NOT</span> <span>NULL</span> <span>DEFAULT</span> <span>'</span><span>0</span><span>'</span> COMMENT <span>'</span><span>登陆次数</span><span>'</span><span>, `update_password` </span><span>int</span>(<span>10</span>) <span>NOT</span> <span>NULL</span> <span>DEFAULT</span> <span>'</span><span>0</span><span>'</span> COMMENT <span>'</span><span>修改密码次数</span><span>'</span><span>, </span><span>PRIMARY</span> <span>KEY</span><span> (`id`), </span><span>KEY</span><span> `pid` (`pid`), </span><span>KEY</span><span> `username` (`username`), </span><span>KEY</span><span> `type` (`type`), </span><span>KEY</span><span> `status` (`status`) ) ENGINE</span><span>=</span>InnoDB <span>DEFAULT</span> CHARSET<span>=</span>utf8 COMMENT<span>=</span><span>'</span><span>登录管理表</span><span>'</span>;
使用Gii创建user模型
将Yii2 basic之前user模型代码导入现在user中(先备份之前basic中的user模型)
<span> 1</span> <span>namespace app\models; </span><span> 2</span> <span> 3</span> <span>use</span><span> Yii; </span><span> 4</span> <span> 5</span> <span>/*</span><span>* </span><span> 6</span> <span> * This is the model class for table "user". </span><span> 7</span> <span> * </span><span> 8</span> <span> * @property integer $id </span><span> 9</span> <span> * @property integer $pid </span><span> 10</span> <span> * @property string $username </span><span> 11</span> <span> * @property string $password </span><span> 12</span> <span> * @property integer $type </span><span> 13</span> <span> * @property integer $created_time </span><span> 14</span> <span> * @property integer $updated_time </span><span> 15</span> <span> * @property integer $status </span><span> 16</span> <span> * @property string $login_ip </span><span> 17</span> <span> * @property integer $login_time </span><span> 18</span> <span> * @property integer $login_count </span><span> 19</span> <span> * @property integer $update_password </span><span> 20</span> <span>*/</span> <span> 21</span> <span>class</span> User <span>extends</span> \yii\db\ActiveRecord <span>implements</span><span> \yii\web\IdentityInterface </span><span> 22</span> <span>{ public $authKey; </span><span> 23</span> <span>/*</span><span>public $id; </span><span> 24</span> <span> public $username; </span><span> 25</span> <span> public $password; </span><span> 26</span> <span> public $authKey; </span><span> 27</span> <span> public $accessToken; </span><span> 28</span> <span> 29</span> <span> private static $users = [ </span><span> 30</span> <span> '100' => [ </span><span> 31</span> <span> 'id' => '100', </span><span> 32</span> <span> 'username' => 'admin', </span><span> 33</span> <span> 'password' => 'admin', </span><span> 34</span> <span> 'authKey' => 'test100key', </span><span> 35</span> <span> 'accessToken' => '100-token', </span><span> 36</span> <span> ], </span><span> 37</span> <span> '101' => [ </span><span> 38</span> <span> 'id' => '101', </span><span> 39</span> <span> 'username' => 'demo', </span><span> 40</span> <span> 'password' => 'demo', </span><span> 41</span> <span> 'authKey' => 'test101key', </span><span> 42</span> <span> 'accessToken' => '101-token', </span><span> 43</span> <span> ], </span><span> 44</span> <span> ]; </span><span> 45</span> <span>*/</span> <span> 46</span> <span> 47</span> <span>/*</span><span>* </span><span> 48</span> <span> * @inheritdoc </span><span> 49</span> <span>*/</span> <span> 50</span> <span>public</span> <span>static</span> <span>function</span><span> tableName() </span><span> 51</span> <span> { </span><span> 52</span> <span>return</span> 'user'<span>; </span><span> 53</span> <span> } </span><span> 54</span> <span> 55</span> <span>/*</span><span>* </span><span> 56</span> <span> * @inheritdoc </span><span> 57</span> <span>*/</span> <span> 58</span> <span>public</span> <span>function</span><span> rules() </span><span> 59</span> <span> { </span><span> 60</span> <span>return</span><span> [ </span><span> 61</span> [['pid', 'type', 'created_time', 'updated_time', 'status', 'login_time', 'login_count', 'update_password'], 'integer'], <span> 62</span> [['username', 'password', 'created_time', 'updated_time', 'login_ip', 'login_time'], 'required'], <span> 63</span> [['username', 'password'], 'string', 'max' => 70], <span> 64</span> [['login_ip'], 'string', 'max' => 20<span>] </span><span> 65</span> <span> ]; </span><span> 66</span> <span> } </span><span> 67</span> <span> 68</span> <span>/*</span><span>* </span><span> 69</span> <span> * @inheritdoc </span><span> 70</span> <span>*/</span> <span> 71</span> <span>public</span> <span>function</span><span> attributeLabels() </span><span> 72</span> <span> { </span><span> 73</span> <span>return</span><span> [ </span><span> 74</span> 'id' => 'ID', <span> 75</span> 'pid' => 'Pid', <span> 76</span> 'username' => 'Username', <span> 77</span> 'password' => 'Password', <span> 78</span> 'type' => 'Type', <span> 79</span> 'created_time' => 'Created Time', <span> 80</span> 'updated_time' => 'Updated Time', <span> 81</span> 'status' => 'Status', <span> 82</span> 'login_ip' => 'Login Ip', <span> 83</span> 'login_time' => 'Login Time', <span> 84</span> 'login_count' => 'Login Count', <span> 85</span> 'update_password' => 'Update Password', <span> 86</span> <span> ]; </span><span> 87</span> <span> } </span><span> 88</span> <span> 89</span> <span>/*</span><span>* </span><span> 90</span> <span> * @inheritdoc </span><span> 91</span> <span>*/</span> <span> 92</span> <span>public</span> <span>static</span> <span>function</span> findIdentity(<span>$id</span><span>) </span><span> 93</span> <span> { </span><span> 94</span> <span>return</span> <span>static</span>::findOne(<span>$id</span><span>); </span><span> 95</span> <span>//</span><span>return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;</span> <span> 96</span> <span> } </span><span> 97</span> <span> 98</span> <span>/*</span><span>* </span><span> 99</span> <span> * @inheritdoc </span><span>100</span> <span>*/</span> <span>101</span> <span>public</span> <span>static</span> <span>function</span> findIdentityByAccessToken(<span>$token</span>, <span>$type</span> = <span>null</span><span>) </span><span>102</span> <span> { </span><span>103</span> <span>return</span> <span>static</span>::findOne(['access_token' => <span>$token</span><span>]); </span><span>104</span> <span>/*</span><span>foreach (self::$users as $user) { </span><span>105</span> <span> if ($user['accessToken'] === $token) { </span><span>106</span> <span> return new static($user); </span><span>107</span> <span> } </span><span>108</span> <span> } </span><span>109</span> <span>110</span> <span> return null;</span><span>*/</span> <span>111</span> <span> } </span><span>112</span> <span>113</span> <span>/*</span><span>* </span><span>114</span> <span> * Finds user by username </span><span>115</span> <span> * </span><span>116</span> <span> * @param string $username </span><span>117</span> <span> * @return static|null </span><span>118</span> <span>*/</span> <span>119</span> <span>public</span> <span>static</span> <span>function</span> findByUsername(<span>$username</span><span>) </span><span>120</span> <span> { </span><span>121</span> <span>$user</span> = User::<span>find() </span><span>122</span> ->where(['username' => <span>$username</span><span>]) </span><span>123</span> -><span>asArray() </span><span>124</span> -><span>one(); </span><span>125</span> <span>126</span> <span>if</span>(<span>$user</span><span>){ </span><span>127</span> <span>return</span> <span>new</span> <span>static</span>(<span>$user</span><span>); </span><span>128</span> <span> } </span><span>129</span> <span>130</span> <span>return</span> <span>null</span><span>; </span><span>131</span> <span>/*</span><span>foreach (self::$users as $user) { </span><span>132</span> <span> if (strcasecmp($user['username'], $username) === 0) { </span><span>133</span> <span> return new static($user); </span><span>134</span> <span> } </span><span>135</span> <span> } </span><span>136</span> <span>137</span> <span> return null;</span><span>*/</span> <span>138</span> <span> } </span><span>139</span> <span>140</span> <span>/*</span><span>* </span><span>141</span> <span> * @inheritdoc </span><span>142</span> <span>*/</span> <span>143</span> <span>public</span> <span>function</span><span> getId() </span><span>144</span> <span> { </span><span>145</span> <span>return</span> <span>$this</span>-><span>id; </span><span>146</span> <span> } </span><span>147</span> <span>148</span> <span>/*</span><span>* </span><span>149</span> <span> * @inheritdoc </span><span>150</span> <span>*/</span> <span>151</span> <span>public</span> <span>function</span><span> getAuthKey() </span><span>152</span> <span> { </span><span>153</span> <span>return</span> <span>$this</span>-><span>authKey; </span><span>154</span> <span> } </span><span>155</span> <span>156</span> <span>/*</span><span>* </span><span>157</span> <span> * @inheritdoc </span><span>158</span> <span>*/</span> <span>159</span> <span>public</span> <span>function</span> validateAuthKey(<span>$authKey</span><span>) </span><span>160</span> <span> { </span><span>161</span> <span>return</span> <span>$this</span>->authKey === <span>$authKey</span><span>; </span><span>162</span> <span> } </span><span>163</span> <span>164</span> <span>/*</span><span>* </span><span>165</span> <span> * Validates password </span><span>166</span> <span> * </span><span>167</span> <span> * @param string $password password to validate </span><span>168</span> <span> * @return boolean if password provided is valid for current user </span><span>169</span> <span>*/</span> <span>170</span> <span>public</span> <span>function</span> validatePassword(<span>$password</span><span>) </span><span>171</span> <span> { </span><span>172</span> <span>return</span> <span>$this</span>->password === <span>$password</span><span>; </span><span>173</span> <span> } </span><span>174</span> }
之前的basic中User模型是继承了\yii\base\Object,为什么要继承这个类,那是因为
<span> 1</span> <span>#</span><span>在\yii\base\Object中,有构造方法</span> <span> 2</span> <span>public</span> <span>function</span> __construct(<span>$config</span> =<span> []) </span><span> 3</span> <span> { </span><span> 4</span> <span>if</span> (!<span>empty</span>(<span>$config</span><span>)) { </span><span> 5</span> Yii::configure(<span>$this</span>, <span>$config</span><span>); </span><span> 6</span> <span> } </span><span> 7</span> <span>$this</span>-><span>init(); </span><span> 8</span> <span> } </span><span> 9</span> <span>#</span><span>继续追踪Yii::configure($this, $config)代码如下 </span> <span>10</span> <span>public</span> <span>static</span> <span>function</span> configure(<span>$object</span>, <span>$properties</span><span>) </span><span>11</span> <span> { </span><span>12</span> <span>foreach</span> (<span>$properties</span> <span>as</span> <span>$name</span> => <span>$value</span><span>) { </span><span>13</span> <span>$object</span>-><span>$name</span> = <span>$value</span><span>; </span><span>14</span> <span> } </span><span>15</span> <span>16</span> <span>return</span> <span>$object</span><span>; </span><span>17</span> <span> } </span><span>18</span> <span>#</span><span>正是因为有这两个方法,所以在User.php中</span> <span>19</span> <span>public</span> <span>static</span> <span>function</span> findByUsername(<span>$username</span><span>) </span><span>20</span> <span> { </span><span>21</span> <span>foreach</span> (self::<span>$users</span> <span>as</span> <span>$user</span><span>) { </span><span>22</span> <span>if</span> (<span>strcasecmp</span>(<span>$user</span>['username'], <span>$username</span>) === 0<span>) { </span><span>23</span> <span>return</span> <span>new</span> <span>static</span>(<span>$user</span><span>); </span><span>24</span> <span> } </span><span>25</span> <span> } </span><span>26</span> <span>27</span> <span>return</span> <span>null</span><span>; </span><span>28</span> <span> } </span><span>29</span> <span>#</span><span>将$user传递过来,通过static,返回一个User的实例。</span>
当通过数据表查询时候没有必要再继承\yii\base\Object,因为不必为类似原来类变量赋值了。这个时候需要User模型继承\yii\db\ActiveRecord,因为要查询用。
findIdentity是根据传递的id返回对应的用户信息,getId返回用户id,getAuthKey和validateAuthKey是作用于登陆中的--记住我。这个authKey是唯一的,当再次登陆时,从cookie中获取authKey传递给validateAuthKey,验证通过,就登陆成功。
插入一条用户模拟数据
INSERT INTO `user` (`username`, `password`) VALUES ('admin', '123')
控制器Controller
<span> 1</span> <span>/*</span><span>* </span><span> 2</span> <span> * 登录 </span><span> 3</span> <span>*/</span> <span> 4</span> <span>public</span> <span>function</span><span> actionLogin() { </span><span> 5</span> <span>if</span> (!\Yii::<span>$app</span>->user-><span>isGuest) { </span><span> 6</span> <span>return</span> <span>$this</span>-><span>goHome(); </span><span> 7</span> <span> } </span><span> 8</span> <span> 9</span> <span>$model</span> = <span>new</span><span> LoginForm(); </span><span>10</span> <span>if</span> (<span>$model</span>->load(Yii::<span>$app</span>->request->post()) && <span>$model</span>-><span>login()) { </span><span>11</span> <span>12</span> <span>13</span> <span>$this</span>->redirect(<span>array</span>('charisma/index'<span>)); </span><span>14</span> } <span>else</span><span> { </span><span>15</span> <span>return</span> <span>$this</span>->render('login',<span> [ </span><span>16</span> 'model' => <span>$model</span>, <span>17</span> <span> ]); </span><span>18</span> <span> } </span><span>19</span> }
veiws中的login.php
<span> 1</span> <div <span>class</span>="well col-md-5 center login-box"> <span> 2</span> <div <span>class</span>="alert alert-info"> <span> 3</span> <span> 请填写您的用户名和密码 </span><span> 4</span> </div> <span> 5</span> <span> 6</span> <?php <span>$form</span> = ActiveForm::<span>begin([ </span><span> 7</span> 'id' => 'login-form', <span> 8</span> ]); ?> <span> 9</span> <span>10</span> <fieldset> <span>11</span> <div <span>class</span>="input-group input-group-lg"> <span>12</span> <span <span>class</span>="input-group-addon"><i <span>class</span>="glyphicon glyphicon-user red"></i></span> <span>13</span> <?php <span>echo</span> Html::input('type','LoginForm[username]', <span>$model</span>->username, ['class'=>'form-control','placeholder'=>'Username']); ?> <span>14</span> </div> <span>15</span> <div <span>class</span>="clearfix"></div><br> <span>16</span> <div <span>class</span>="input-group input-group-lg"> <span>17</span> <span <span>class</span>="input-group-addon"><i <span>class</span>="glyphicon glyphicon-lock red"></i></span> <span>18</span> <?php <span>echo</span> Html::input('password','LoginForm[password]', <span>$model</span>->password, ['class'=>'form-control','placeholder'=>'Password']); ?> <span>19</span> </div> <span>20</span> <div <span>class</span>="clearfix"></div> <span>21</span> <span>22</span> <div <span>class</span>="clearfix"></div> <span>23</span> <p <span>class</span>="center col-md-5"> <span>24</span> <input type="submit" <span>class</span>="btn btn-primary" value="Login"> <span>25</span> </p> <span>26</span> </fieldset> <span>27</span> <?php ActiveForm::<span>end</span>();?> <span>28</span> <span>29</span> <?<span>php </span><span>30</span> <span>if</span>(<span>$model</span>-><span>errors){ </span><span>31</span> <span>echo</span> '用户名或密码错误'<span>; </span><span>32</span> <span>print_r</span>(<span>$model</span>-><span>errors); </span><span>33</span> <span> } </span><span>34</span> <span>35</span> <span>36</span> <span>37</span> ?> <span>38</span> <span>39</span> </div>
用户名admin, 密码123, 登录ok!
问题来了,我们使用的是明文保存的密码,这样很不安全,所以我们必须要把用户注册时的密码哈希加密后再保存到数据库。
YII2对密码加密生成的结果是不同的,即用相同的初始密码在不同时间得到的加密结果不同,所以我们不能用常用的方法去验证密码是否正确(将密码加密后与数据库中的密码相比较)。YII2有自己的加密以及密码验证流程。
加密
<span>$hash</span> = Yii::<span>$app</span>->getSecurity()->generatePasswordHash('123456');
验证
Yii::<span>$app</span>->getSecurity()->validatePassword('123456', <span>$hash</span>) ; <span>#</span><span>,返回true或false</span>
我们先通过Yii的加密机制加密 “123” 获取哈希密码为: $2y$13$eXQl9YCo5XcKqqy9ymd2t.SuOvpXYERidceXoT/bPt4iwmOW3GiBy
修改模拟数据admin的密码:
<span>UPDATE</span> `<span>user</span>` <span>SET</span> `password`<span>=</span><span>'</span><span>$2y$13$eXQl9YCo5XcKqqy9ymd2t.SuOvpXYERidceXoT/bPt4iwmOW3GiBy</span><span>'</span> <span>WHERE</span> (`username`<span>=</span><span>'</span><span>admin</span><span>'</span>)
在控制器中我们通过 实例化LoginForm,
Yii::$app->request->post()来获取post提交的值,通过$model->load()加载post数据
然后$model->login() 就是验证登录
<span>$model</span> = <span>new</span><span> LoginForm(); </span><span>if</span> (<span>$model</span>->load(Yii::<span>$app</span>->request->post()) && <span>$model</span>-><span>login()) { </span><span>$this</span>->redirect(<span>array</span>('charisma/index'<span>)); }</span>
我们跳转到app\models\LoginForm的login方法
<span>public</span> <span>function</span><span> login() { </span><span>if</span> (<span>$this</span>-><span>validate()) { </span><span>return</span> Yii::<span>$app</span>->user->login(<span>$this</span>->getUser(), <span>$this</span>->rememberMe ? 3600*24*30 : 0<span>); } </span><span>else</span><span> { </span><span>return</span> <span>false</span><span>; } }</span>
login方法又是通过一个validate验证方法 继承vendor/yiisoft/yii2/base/Model.php
该验证方法描述是这样的:Performs the data validation. This method executes the validation rules applicable to the current [[scenario]]. The following criteria are used to determine whether a rule is currently applicable: - the rule must be associated with the attributes relevant to the current scenario; - the rules must be effective for the current scenario. This method will call [[beforeValidate()]] and [[afterValidate()]] before and after the actual validation, respectively. If [[beforeValidate()]] returns false, the validation will be cancelled and [[afterValidate()]] will not be called. Errors found during the validation can be retrieved via [[getErrors()]], [[getFirstErrors()]] and [[getFirstError()]].
我们打开model类的validate()
<span>public</span> <span>function</span> validate(<span>$attributeNames</span> = <span>null</span>, <span>$clearErrors</span> = <span>true</span><span>) { </span><span>if</span> (<span>$clearErrors</span><span>) { </span><span>$this</span>-><span>clearErrors(); } </span><span>if</span> (!<span>$this</span>-><span>beforeValidate()) { </span><span>return</span> <span>false</span><span>; } </span><span>$scenarios</span> = <span>$this</span>-><span>scenarios(); </span><span>$scenario</span> = <span>$this</span>-><span>getScenario(); </span><span>if</span> (!<span>isset</span>(<span>$scenarios</span>[<span>$scenario</span><span>])) { </span><span>throw</span> <span>new</span> InvalidParamException("Unknown scenario: <span>$scenario</span>"<span>); } </span><span>if</span> (<span>$attributeNames</span> === <span>null</span><span>) { </span><span>$attributeNames</span> = <span>$this</span>-><span>activeAttributes(); } </span><span>foreach</span> (<span>$this</span>->getActiveValidators() <span>as</span> <span>$validator</span><span>) { </span><span>$validator</span>->validateAttributes(<span>$this</span>, <span>$attributeNames</span><span>); } </span><span>$this</span>-><span>afterValidate(); </span><span>return</span> !<span>$this</span>-><span>hasErrors(); }</span>
也就是说获取到场景且没有错误的话,将场景yii\validators\RequiredValidator Object的每一个属性实例化为对应Form规则(rules)实例
<span>foreach</span> (<span>$this</span>->getActiveValidators() <span>as</span> <span>$validator</span><span>) { </span><span>$validator</span>->validateAttributes(<span>$this</span>, <span>$attributeNames</span><span>); }</span>
现在找到LoginForm的验证规则
<span>/*</span><span>* * @return array the validation rules. </span><span>*/</span> <span>public</span> <span>function</span><span> rules() { </span><span>return</span><span> [ </span><span>//</span><span> username and password are both required</span> [['username', 'password'], 'required'], <span>//</span><span> rememberMe must be a boolean value</span> ['rememberMe', 'boolean'], <span>//</span><span> password is validated by validatePassword()</span> ['password', 'validatePassword'],<span> ]; }</span>
其中username,password 必填, rememberMe为波尔类型, password通过ValidatePassword方法来验证
查看validatePassword方法
<span>/*</span><span>* * Validates the password. * This method serves as the inline validation for password. * * @param string $attribute the attribute currently being validated * @param array $params the additional name-value pairs given in the rule </span><span>*/</span> <span>public</span> <span>function</span> validatePassword(<span>$attribute</span>, <span>$params</span><span>) { </span><span>if</span> (!<span>$this</span>-><span>hasErrors()) { </span><span>$user</span> = <span>$this</span>-><span>getUser(); </span><span>if</span> (!<span>$user</span> || !<span>$user</span>->validatePassword(<span>$this</span>-><span>password)) { </span><span>$this</span>->addError(<span>$attribute</span>, 'Incorrect username or password.'<span>); } } }</span>
首先$this->getUser()会判断在user表中是否有username=“admin”,如果存在就返回一个user的实例
<span>public</span> <span>static</span> <span>function</span> findByUsername(<span>$username</span><span>) { </span><span>$user</span> = User::<span>find() </span>->where(['username' => <span>$username</span><span>]) </span>-><span>asArray() </span>-><span>one(); </span><span>if</span> (<span>$user</span><span>) { </span><span>return</span> <span>new</span> <span>static</span>(<span>$user</span><span>); } </span><span>return</span> <span>null</span><span>; }</span>
通过$user->validatePassword($this->password) 判断验证密码,这个是最关键的一步
因为之前通过$this->getUser 已经实例化了user表,所以validatePassword在User模型的原始代码是这样的
<span>/*</span><span>* * Validates password * * @param string $password password to validate * @return boolean if password provided is valid for current user </span><span>*/</span> <span>public</span> <span>function</span> validatePassword(<span>$password</span><span>) { </span><span>return</span> <span>$this</span>->password === <span>$password</span><span>; }</span>
获取用户输入的密码, 再和数据库中的密码做对比,如果密码相同就通过验证。
现在我们已经把密码123改为哈希密码:$2y$13$eXQl9YCo5XcKqqy9ymd2t.SuOvpXYERidceXoT/bPt4iwmOW3GiBy
所以要通过Yii2 自带的验证 Yii::$app->getSecurity()->validatePassword('123456', $hash) ; 进行验证
所以validatePassword方法的代码应该修改如下:
<span>/*</span><span>* * Validates password * * @param string $password password to validate * @return boolean if password provided is valid for current user </span><span>*/</span> <span>public</span> <span>function</span> validatePassword(<span>$password</span><span>) { </span><span>return</span> Yii::<span>$app</span>->getSecurity()->validatePassword(<span>$password</span>, <span>$this</span>-><span>password); }</span>
完整的LoginForm模型和User模型代码如下:
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>namespace app\models; </span><span> 4</span> <span> 5</span> <span>use</span><span> Yii; </span><span> 6</span> <span>use</span><span> yii\base\Model; </span><span> 7</span> <span> 8</span> <span>/*</span><span>* </span><span> 9</span> <span> * LoginForm is the model behind the login form. </span><span>10</span> <span>*/</span> <span>11</span> <span>class</span> LoginForm <span>extends</span><span> Model </span><span>12</span> <span>{ </span><span>13</span> <span>public</span> <span>$username</span><span>; </span><span>14</span> <span>public</span> <span>$password</span><span>; </span><span>15</span> <span>public</span> <span>$rememberMe</span> = <span>true</span><span>; </span><span>16</span> <span>17</span> <span>private</span> <span>$_user</span> = <span>false</span><span>; </span><span>18</span> <span>19</span> <span>20</span> <span>/*</span><span>* </span><span>21</span> <span> * @return array the validation rules. </span><span>22</span> <span>*/</span> <span>23</span> <span>public</span> <span>function</span><span> rules() </span><span>24</span> <span> { </span><span>25</span> <span>return</span><span> [ </span><span>26</span> <span>//</span><span> username and password are both required</span> <span>27</span> [['username', 'password'], 'required'], <span>28</span> <span>//</span><span> rememberMe must be a boolean value</span> <span>29</span> ['rememberMe', 'boolean'], <span>30</span> <span>//</span><span> password is validated by validatePassword()</span> <span>31</span> ['password', 'validatePassword'], <span>32</span> <span> ]; </span><span>33</span> <span> } </span><span>34</span> <span>35</span> <span>/*</span><span>* </span><span>36</span> <span> * Validates the password. </span><span>37</span> <span> * This method serves as the inline validation for password. </span><span>38</span> <span> * </span><span>39</span> <span> * @param string $attribute the attribute currently being validated </span><span>40</span> <span> * @param array $params the additional name-value pairs given in the rule </span><span>41</span> <span>*/</span> <span>42</span> <span>public</span> <span>function</span> validatePassword(<span>$attribute</span>, <span>$params</span><span>) </span><span>43</span> <span> { </span><span>44</span> <span>if</span> (!<span>$this</span>-><span>hasErrors()) { </span><span>45</span> <span>$user</span> = <span>$this</span>-><span>getUser(); </span><span>46</span> <span>47</span> <span>if</span> (!<span>$user</span> || !<span>$user</span>->validatePassword(<span>$this</span>-><span>password)) { </span><span>48</span> <span>$this</span>->addError(<span>$attribute</span>, 'Incorrect username or password.'<span>); </span><span>49</span> <span> } </span><span>50</span> <span> } </span><span>51</span> <span> } </span><span>52</span> <span>53</span> <span>/*</span><span>* </span><span>54</span> <span> * Logs in a user using the provided username and password. </span><span>55</span> <span> * @return boolean whether the user is logged in successfully </span><span>56</span> <span>*/</span> <span>57</span> <span>public</span> <span>function</span><span> login() </span><span>58</span> <span> { </span><span>59</span> <span>if</span> (<span>$this</span>-><span>validate()) { </span><span>60</span> <span>return</span> Yii::<span>$app</span>->user->login(<span>$this</span>->getUser(), <span>$this</span>->rememberMe ? 3600*24*30 : 0<span>); </span><span>61</span> } <span>else</span><span> { </span><span>62</span> <span>return</span> <span>false</span><span>; </span><span>63</span> <span> } </span><span>64</span> <span> } </span><span>65</span> <span>66</span> <span>/*</span><span>* </span><span>67</span> <span> * Finds user by [[username]] </span><span>68</span> <span> * </span><span>69</span> <span> * @return User|null </span><span>70</span> <span>*/</span> <span>71</span> <span>public</span> <span>function</span><span> getUser() </span><span>72</span> <span> { </span><span>73</span> <span>if</span> (<span>$this</span>->_user === <span>false</span><span>) { </span><span>74</span> <span>$this</span>->_user = User::findByUsername(<span>$this</span>-><span>username); </span><span>75</span> <span> } </span><span>76</span> <span>77</span> <span>return</span> <span>$this</span>-><span>_user; </span><span>78</span> <span> } </span><span>79</span> }
<?<span>php namespace app\models; </span><span>use</span><span> Yii; </span><span>/*</span><span>* * This is the model class for table "user". * * @property integer $id * @property integer $pid * @property string $username * @property string $password * @property integer $type * @property integer $created_time * @property integer $updated_time * @property integer $status * @property string $login_ip * @property integer $login_time * @property integer $login_count * @property integer $update_password </span><span>*/</span> <span>class</span> User <span>extends</span> \yii\db\ActiveRecord <span>implements</span><span> \yii\web\IdentityInterface { public $authKey; </span><span>/*</span><span>* * @inheritdoc </span><span>*/</span> <span>public</span> <span>static</span> <span>function</span><span> tableName() { </span><span>return</span> 'user'<span>; } </span><span>/*</span><span>* * @inheritdoc </span><span>*/</span> <span>public</span> <span>function</span><span> rules() { </span><span>return</span><span> [ [[</span>'pid', 'type', 'created_time', 'updated_time', 'status', 'login_time', 'login_count', 'update_password'], 'integer'],<span> [[</span>'username', 'password', 'created_time', 'updated_time', 'login_ip', 'login_time'], 'required'],<span> [[</span>'username', 'password'], 'string', 'max' => 70],<span> [[</span>'login_ip'], 'string', 'max' => 20<span>] ]; } </span><span>/*</span><span>* * @inheritdoc </span><span>*/</span> <span>public</span> <span>function</span><span> attributeLabels() { </span><span>return</span><span> [ </span>'id' => 'ID', 'pid' => 'Pid', 'username' => 'Username', 'password' => 'Password', 'type' => 'Type', 'created_time' => 'Created Time', 'updated_time' => 'Updated Time', 'status' => 'Status', 'login_ip' => 'Login Ip', 'login_time' => 'Login Time', 'login_count' => 'Login Count', 'update_password' => 'Update Password',<span> ]; } </span><span>/*</span><span>* * @inheritdoc </span><span>*/</span> <span>public</span> <span>static</span> <span>function</span> findIdentity(<span>$id</span><span>) { </span><span>return</span> <span>static</span>::findOne(<span>$id</span><span>); } </span><span>/*</span><span>* * @inheritdoc </span><span>*/</span> <span>public</span> <span>static</span> <span>function</span> findIdentityByAccessToken(<span>$token</span>, <span>$type</span> = <span>null</span><span>) { </span><span>return</span> <span>null</span><span>; } </span><span>/*</span><span>* * Finds user by username * * @param string $username * @return static|null </span><span>*/</span> <span>public</span> <span>static</span> <span>function</span> findByUsername(<span>$username</span><span>) { </span><span>$user</span> = User::<span>find() </span>->where(['username' => <span>$username</span><span>]) </span>-><span>asArray() </span>-><span>one(); </span><span>if</span> (<span>$user</span><span>) { </span><span>return</span> <span>new</span> <span>static</span>(<span>$user</span><span>); } </span><span>return</span> <span>null</span><span>; } </span><span>/*</span><span>* * @inheritdoc </span><span>*/</span> <span>public</span> <span>function</span><span> getId() { </span><span>return</span> <span>$this</span>-><span>id; } </span><span>/*</span><span>* * @inheritdoc </span><span>*/</span> <span>public</span> <span>function</span><span> getAuthKey() { </span><span>return</span> <span>$this</span>-><span>authKey; } </span><span>/*</span><span>* * @inheritdoc </span><span>*/</span> <span>public</span> <span>function</span> validateAuthKey(<span>$authKey</span><span>) { </span><span>return</span> <span>$this</span>->authKey === <span>$authKey</span><span>; } </span><span>/*</span><span>* * Validates password * * @param string $password password to validate * @return boolean if password provided is valid for current user </span><span>*/</span> <span>public</span> <span>function</span> validatePassword(<span>$password</span><span>) { </span><span>return</span> Yii::<span>$app</span>->getSecurity()->validatePassword(<span>$password</span>, <span>$this</span>->password); <span>#</span><span>,返回true或false</span> <span> } </span><span>#</span><span>-------------------------------------辅助验证-----------------------------------------------------------</span> <span>public</span> <span>function</span><span> createhashpasswd(){ </span><span>echo</span> Yii::<span>$app</span>->getSecurity()->generatePasswordHash('123'<span>); } }</span>
ok,这样就实现了哈希加密的用户登录了。