一、准备

在开始编写代码之前,我们需要思考一下:用户登陆模块,实现的是什么功能?很明显,是登陆功能,那么,登陆需要用户名和密码,我们在数据库的一张表中就应该准备好用户名和密码的字段,再思考一下,如果要实现自动登陆的功能,那么还需要什么?Cookie,是专门用于自动登陆的,所以,我们的数据表可能需要准备一个字段,专门用于储存客户端登陆所生成的cookie,这样,就能通过验证客户端和服务端的cookie是否相同来进行自动登陆了。基于以上思考,我们的数据表应该包含以下字段:
id(primarykey,auto_increment),username(varchar),password(varchar(32)),auth_key(varchar(32)),accessToken(varchar(32))(这个暂不解释,后文解释).
1、首先,建立一个数据库:myDatabase,
2、然后建立一张数据表:user,增加上述字段。
对于如何建数据库和建表,这里不再赘述。

二、模型(Model)

Yii框架采用MVC设计模式,所以Model是一个模块的核心所在,所以我们先完成对Model的编写。

1、LoginForm.php

用户登陆模块,所提交的是username和password,所以我们要先建立一个Model,专门处理用户提交的数据,所以先新建一个LoginForm.php,以下为代码:

  1. <?php
  2. namespace app\modules\backend\models;
  3. use Yii;
  4. use yii\base\Model;
  5. /**
  6. * LoginForm is the model behind the login form.
  7. */
  8. class LoginForm extends Model
  9. {
  10. public $username;
  11. public $password;
  12. public $rememberMe = true;
  13. private $_user = false;
  14. /**
  15. * @return array the validation rules.
  16. */
  17. public function rules()<span style="white-space:pre">     </span>//①
  18. {
  19. return [
  20. // username and password are both required
  21. [['username', 'password'], 'required','message'=>""],
  22. // rememberMe must be a boolean value
  23. ['rememberMe', 'boolean'],
  24. // password is validated by validatePassword()
  25. ['password', 'validatePassword'],
  26. ];
  27. }
  28. /**
  29. * Validates the password.
  30. * This method serves as the inline validation for password.
  31. *
  32. * @param string $attribute the attribute currently being validated
  33. * @param array $params the additional name-value pairs given in the rule
  34. */
  35. public function validatePassword($attribute, $params)
  36. {
  37. if (!$this->hasErrors()) {
  38. $user = $this->getUser();
  39. if (!$user || !$user->validatePassword($this->password)) {
  40. $this->addError($attribute, 'Incorrect username or password.');
  41. }
  42. }
  43. }
  44. /**
  45. * Logs in a user using the provided username and password.
  46. * @return boolean whether the user is logged in successfully
  47. */
  48. public function login()
  49. {
  50. if ($this->validate()) {
  51. if($this->rememberMe)
  52. {
  53. $this->_user->generateAuthKey();//③
  54. }
  55. return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
  56. }
  57. return false;
  58. }
  59. /**
  60. * Finds user by [[username]]
  61. *
  62. * @return User|null
  63. */
  64. public function getUser()
  65. {
  66. if ($this->_user === false) {
  67. $this->_user = User::findByUsername($this->username); //②
  68. }
  69. return $this->_user;
  70. }
  71. }

该Model是根据basic模板自带的LoginForm修改而成,代码中大多有注释,这里关注以下代码:

①号代码处是rules规则,rules规则定义了填充过来的数据的规则,验证所填的数据是否为空,是否符合格式之类的,其中有一栏是password,对应的规则是validatePassword,会自动调用当前类的validatePassword()方法,注意与下文的User类对应的方法区分。

②号代码,调用了User类里面的findByUsername方法,这个User类下面会写到,主要是为了返回一个AR类实例,与当前LoginForm的数据进行比较。

③号代码,这里暂时不提,等讲到cookie登陆的时候再提。

2、User.php

(1)ActiveRecord 类

在完成LoginForm后,我们还缺少一些东西,从用户接受到数据了,那么还需要从数据库取出相应的数据来进行比较,所以我们接下来需要完成的是一个从数据库获取的数据的类——AR类,全称是ActiveRecord,活动记录类,方便用于查找数据,只要类名和数据表的表名相同,那么它就能从这个数据表中获取数据,比如说这样:

  1. <?php
  2. namespace app\modules\backend\models;
  3. use yii\db\ActiveRecord;
  4. class User extends ActiveRecord{       } ?>

此外,还能自己添加返回的表名,只要在这个类中重写以下方法:

  1. public static function tableName(){
  2. return 'user';
  3. }

(2)IdentityInterface 接口

一般来说,从数据库查找数据,只需要继承AR类即可,但是,我们这个是用户登录模型,核心是验证,所以自然需要实现核心的验证功能,就像LoginForm模型提到的validatePassword一样,实际的验证逻辑是在当前的User模型完成的。一般来说,实现IdentityInterface接口,需要实现以下方法:

  1. public static function findIdentity($id);  //①
  2. public static function findIdentityByAccessToken($token, $type = null);   //②
  3. public function getId();    //③
  4. public function getAuthKey();   //④
  5. public function validateAuthKey($authKey);    //⑤

①findIdentity:是根据id查找数据表对应的数据

②findIdentityByAccessToken是根据AccessToken(上文提到的)查找对应的数据,而AccessToken我们在数据表也有这个字段,那么它到底有什么用呢?其实AccessToken在我们当前的用户登陆模型中用处并不大,它是专门用于Resetful登陆验证用到的,具体可自行百度,这里不展开说明。

③getId:返回当前AR类所对应的id

④getAuthKey:返回当前AR类所对应的auth_key

⑤validateAuthKey:这个方法比较重要,是我们后面要讲到的cookie登陆验证的核心所在。

好了,既然知道了这五个方法的用处,那么我们在我们的User.php实现接口,然后重写以上方法,完整的User.php的代码如下:

  1. <?php
  2. namespace app\modules\backend\models;
  3. use yii\db\ActiveRecord;
  4. class User extends ActiveRecord implements \yii\web\IdentityInterface
  5. {
  6. public static function tableName(){
  7. return 'user';
  8. }
  9. public static function findIdentity($id){
  10. return static::findOne($id);
  11. }
  12. public static function findIdentityByAccessToken($token,$type=null){
  13. return static::findOne(['accessToken'=>$token]);
  14. }
  15. public static function findByUsername($username){     //①
  16. return static::findOne(['username'=>$username]);
  17. }
  18. public function getId(){
  19. return $this->id;
  20. }
  21. public function getAuthkey(){
  22. return $this->auth_key;
  23. }
  24. public function validateAuthKey($authKey){
  25. return $this->auth_key === $authKey;
  26. }
  27. public function validatePassword($password){          //②
  28. return $this->password === md5($password);
  29. }
  30. <span style="white-space:pre"> </span> /**
  31. <span style="white-space:pre">    </span> * Generates "remember me" authentication key
  32. <span style="white-space:pre">    </span> */
  33. public function generateAuthKey()                    //③
  34. {
  35. <span style="white-space:pre">     </span>$this->auth_key = \Yii::$app->security->generateRandomString();
  36. <span style="white-space:pre">     </span>$this->save();
  37. }
  38. }
  39. ?>

这里分析其中的三个方法:

①findByUsername():在LoginForm的代码中,引用了这个方法,目的是根据用户提交的username返回一个在数据表与username相同的数据项,即AR实例。

②validatePassword():这里对用户提交的密码以及当前AR类的密码进行比较。

③generateAuthKey():生成随机的auth_key,用于cookie登陆。

到此,我们完成了Model的编写,一共写了两个Model类:LoginForm和User,一个用于接收用户提交的数据,一个用于获取数据库的数据,接下来我们编写Controller.

三、控制器(Controller)

控制器,主要是用于数据的提交,把用户提交的数据填充到相应的模型(Model)中,然后根据模型返回的信息进一步渲染视图(View),或者执行其他逻辑。

这里,把控制器命名为LoginController.php,以下是完整的实现代码:

  1. <?php
  2. namespace app\controllers;
  3. use Yii;
  4. use yii\filters\AccessControl;
  5. use yii\web\Controller;
  6. use yii\filters\VerbFilter;
  7. use app\models\LoginForm;
  8. use app\models\ContactForm;
  9. class SiteController extends Controller
  10. {
  11. public function actionIndex()
  12. {
  13. return $this->render('index');
  14. }
  15. public function actionLogin()
  16. {
  17. if (!\Yii::$app->user->isGuest) {     //①
  18. return $this->goHome();
  19. }
  20. $model = new LoginForm();             //②
  21. if ($model->load(Yii::$app->request->post()) && $model->login()) {      //③
  22. return $this->goBack();          //④
  23. }
  24. return $this->render('login', [      //⑤
  25. 'model' => $model,
  26. ]);
  27. }
  28. public function actionLogout()
  29. {
  30. Yii::$app->user->logout();
  31. return $this->goHome();
  32. }
  33. }

关注其中的actionLogin()方法:

①首先从\Yii::$app->user->isGuest中判断,当前是否是游客模式,即未登陆状态,如果用户已经登陆,会在user类中储存当前登陆用户的信息。

②如果当前是游客,会先实例化一个LoginForm模型

③这行代码是整个login方法的核心所在,首先:$model->load(Yii::$app->request->post())把post过来的数据填充进$model,即LoginForm模型,如果返回true,则填充成功。接着:$model->login():执行LoginForm类里面的login()方法,可以从login()方法里面看到,将会执行一系列的验证。

关于Yii框架到底是怎样进行用户登陆的,底层是怎样实现的,我们在下一篇文章详谈,这里先说明实现方法。

四、视图(View)

在实现了model和controller,接下来是视图部分,由于用户需要输入数据,所以我们要提供一个表单,在Yii2中,提供了ActiveForm快速生成表单,代码如下:

  1. <?php
  2. /* @var $this yii\web\View */
  3. /* @var $form yii\bootstrap\ActiveForm */
  4. /* @var $model app\models\LoginForm */
  5. use yii\helpers\Html;
  6. use yii\bootstrap\ActiveForm;
  7. $this->title = 'Login';
  8. $this->params['breadcrumbs'][] = $this->title;
  9. ?>
  10. <div class="site-login">
  11. <h1><?= Html::encode($this->title) ?></h1>
  12. <p>Please fill out the following fields to login:</p>
  13. <?php $form = ActiveForm::begin([
  14. 'id' => 'login-form',
  15. 'options' => ['class' => 'form-horizontal'],
  16. 'fieldConfig' => [
  17. 'template' => "{label}\n<div class=\"col-lg-3\">{input}</div>\n<div class=\"col-lg-8\">{error}</div>",
  18. 'labelOptions' => ['class' => 'col-lg-1 control-label'],
  19. ],
  20. ]); ?>
  21. <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
  22. <?= $form->field($model, 'password')->passwordInput() ?>
  23. <?= $form->field($model, 'rememberMe')->checkbox([
  24. 'template' => "<div class=\"col-lg-offset-1 col-lg-3\">{input} {label}</div>\n<div class=\"col-lg-8\">{error}</div>",
  25. ]) ?>
  26. <div class="form-group">
  27. <div class="col-lg-offset-1 col-lg-11">
  28. <?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
  29. </div>
  30. </div>
  31. <?php ActiveForm::end(); ?>
  32. <div class="col-lg-offset-1" style="color:#999;">
  33. You may login with <strong>admin/admin</strong> or <strong>demo/demo</strong>.<br>
  34. To modify the username/password, please check out the code <code>app\models\User::$users</code>.
  35. </div>
  36. </div>

$form=ActiveForm::begin() :创建一个Form表单

$form=field()->textInput()   :创建一个文本输入框

$form=field()->checkbox() :创建一个checkbox

Html::submitButton():          创建一个登陆按钮

ActiveForm::end()    :   结束表单

以上,就是创建一个用户登陆模块的全流程,这里对用户登陆的细节和怎样实现cookie自动登陆只是一笔带过,更详细的源码分析请看下一篇博文,谢谢。

Yii2.0 用户登录详解(上)相关推荐

  1. mysql 用户管理表_Mysql—用户表详解(mysql.user)

    MySQL 数据库 Mysql-用户表详解(mysql.user) MySQL是一个多用户管理的数据库,可以为不同用户分配不同的权限,分为root用户和普通用户,root用户为超级管理员,拥有所有权限 ...

  2. python获取登录后的cookie_python爬虫使用cookie登录详解

    前言: 什么是cookie? Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密). 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想 ...

  3. Linux用户管理详解大结局(下)

    Linux用户管理详解(下) 我们已经可以通过创建不同的用户来防止其他人使用自己的账号,之后每个账户对应一个单独的用户密码,构成了一个基本的用户管理思路.为了方便管理还可以使用组来设置相同属性的用户. ...

  4. linux 帐号 配置sftp_Linux 下sftp配置之密钥方式登录详解

    Linux下sftp配置之密钥方式登录 由于vsftp采用明文传输,用户名密码可通过抓包得到,为了安全性,需使用sftp,锁定目录且不允许sftp用户登到服务器.由于sftp使用的是ssh协议,需保证 ...

  5. android拍照保存照片方向,Android:Camera2开发详解(上):实现预览、拍照、保存照片等功能...

    android.jpg 前言 在前几篇文章中介绍了如何调用系统相机拍照和使用Camera1的实现自定义相机拍照.人脸检测等功能 文章传送门: 接下来的几篇文章中,我将给大家介绍如何使用Camera2实 ...

  6. kubernetespod控制器详解上

    kubernetespod控制器详解上 pod调度策略之污点和容忍 污点(Taints) 通过在Pod上添加属性,来确定Pod是否要调度到指定的Node上,其实我们也可以站在Node的角度上,通过在N ...

  7. nginx1.0安装配置详解

    nginx1.0安装配置详解 本文转自:twenty_four的博文,自己稍作精简修改. http://twentyfour.blog.51cto.com/945260/568906 1.选择Ngin ...

  8. Oracle Golden Gate 11.2.0.3安装详解

    Oracle Golden Gate 11.2.0.3安装详解 环境 环境变量 安装OGG软件 开始OGG配置 配置源端数据库 源端OGG配置 配置目标端数据库 目标端OGG配置 开启同步 环境 ce ...

  9. 【破解教程】PE文件格式详解(上)

    PE文件格式详解(上) 摘要 Windows NT 3.1引入了一种名为PE文件格式的新可执行文件格式.PE文件格式的规范包含在了MSDN的CD中(Specs and Strategy, Specif ...

最新文章

  1. vue 返回滚动条顶部组件_vue中回到顶部
  2. HDU 4602 - Partition
  3. java高级用法之:调用本地方法的利器JNA
  4. mongoose 笔记
  5. jzoj4017-逃跑【0/1分数规划,线段树,dp】
  6. 分布式 | Dubbo 架构设计详解
  7. OpenGL进阶演示样例1——动态画线(虚线、实线、颜色、速度等)
  8. TCP转输控制协议(转)
  9. LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话(简单易懂)
  10. mybitis SQL insert into 多条数据
  11. php输出最近N个月的起至时间戳
  12. 裴礼文3.2.34解答
  13. R计算两列数据的相关系数_【R语言】相关性分析、相关系数的显著性检验及可视化...
  14. STM32f103系列各个型号芯片之间的程序移植
  15. 运营方法 - 运营的思考方法
  16. Python自动化测试框架有哪些?(总结几种)
  17. 制作标准1寸和2寸照片方法
  18. 比editplus好用的编辑器sublime text3
  19. ViewFlipper和ViewPager的区别
  20. 新版傻妞升级之后 登录 查询无反应

热门文章

  1. Web前端学习(千锋)
  2. 两台电脑间USB传输文件
  3. FIDDLER的使用方法及技巧总结[连载2]---FIDDLER用户界面
  4. 浮躁与投机取巧 (干一行爱一行,学会沉淀)
  5. 利用淘宝指数做产品数据分析
  6. 树立个人品牌:让名企hr们主动来找你
  7. MIPI传输全局流程图
  8. 1075 PAT Judge 测试点四
  9. matlab黎曼问题roe格式,Godnov_HLLC 解1D黎曼问题的有限体积法,使用Roe格式做近似 Algorithm 数学计算 238万源代码下载- www.pudn.com...
  10. Cris 的 Python 数据分析笔记 08:NumPy 和 Pandas 整理脑图