首頁 >php教程 >php手册 >Yii2 用户登录,Yii2用户登录

Yii2 用户登录,Yii2用户登录

WBOY
WBOY原創
2016-06-13 08:57:32941瀏覽

Yii2 用户登录,Yii2用户登录

在Yii2的basic版本中默认是从一个数组验证用户名和密码,如何改为从数据表中查询验证呢?且数据库的密码要为哈希加密密码验证?

下面我们就一步一步解析Yii2的登录过程。

一. 创建user表模型

表结构如下:

<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!

问题来了,我们使用的是明文保存的密码,这样很不安全,所以我们必须要把用户注册时的密码哈希加密后再保存到数据库。

 

三. Yii的密码加密

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,这样就实现了哈希加密的用户登录了。

 

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn