Heim >Backend-Entwicklung >PHP-Tutorial >Yii2 用户登录,Yii2用户登录_PHP教程

Yii2 用户登录,Yii2用户登录_PHP教程

WBOY
WBOYOriginal
2016-07-13 09:46:011177Durchsuche

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

 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1036618.htmlTechArticleYii2 用户登录,Yii2用户登录 在Yii2的basic版本中默认是从一个数组验证用户名和密码,如何改为从数据表中查询验证呢?且数据库的密码要为...
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn