一、准备

在开始编写代码之前,我们需要思考一下:用户登陆模块,实现的是什么功能?很明显,是登陆功能,那么,登陆需要用户名和密码,我们在数据库的一张表中就应该准备好用户名和密码的字段,再思考一下,如果要实现自动登陆的功能,那么还需要什么?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自动登陆只是一笔带过,更详细的源码分析请看下一篇博文,谢谢。

ps:本文转自他人,并非原创

Yii2.0 用户登录详解(上)的更多相关文章

  1. yii2.0用户登录,退出判断(摘录)

    文章来源:http://blog.sina.com.cn/s/blog_88a65c1b0101ix13.html 判断用户是否登录 在 Yii2.0 里面,判断用户是否已经登录,我们用下面的代码即可 ...

  2. 关于NopCommerce3.6版用户登录详解

    一.登录方式 Nop登录方式有两种(且只能选择一种方式登录):一种是用用户名登录,另一种是用户注册邮箱登录,这个在后台可配置: 第一种:用户名登录 后台配置路径在商城设置à设置管理à客户设置:使用用户 ...

  3. 如何修改yii2.0用户登录使用的user表为其它的表

      这只是自己练习的一个记录而已. 因为某种原因,不想用yii自带的user表,想用自己建的admin数据库表,修改如下: 1. 参考高级模板里里的common\models\User 修改 Admi ...

  4. sql server 2008 数据库管理系统使用SQL语句创建登录用户步骤详解

    介绍了sql server 2008 数据库管理系统使用SQL语句创建登录用户步骤详解 --服务器角色: --固定服务器角色具有一组固定的权限,并且适用于整个服务器范围. 它们专门用于管理 SQL S ...

  5. 转 OAuth 2.0授权协议详解

    http://www.jb51.net/article/54948.htm 作者:阮一峰 字体:[增加 减小] 类型:转载 时间:2014-09-10我要评论 这篇文章主要介绍了OAuth 2.0授权 ...

  6. linux ssh使用深度解析(key登录详解)

    linux ssh使用深度解析(key登录详解) SSH全称Secure SHell,顾名思义就是非常安全的shell的意思,SSH协议是IETF(Internet Engineering Task ...

  7. SSL/TLS协议详解(上):密码套件,哈希,加密,密钥交换算法

    本文转载自SSL/TLS协议详解(上):密码套件,哈希,加密,密钥交换算法 导语 作为一名安全爱好者,我一向很喜欢SSL(目前是TLS)的运作原理.理解这个复杂协议的基本原理花了我好几天的时间,但只要 ...

  8. Linux常用命令详解上

    Linux常用命令详解上 目录 一.shell 二.Linux命令 2.1.内部命令与外部命令的区别 2.2.Linux命令行的格式 2.3.编辑Linux命令行的辅助操作 2.4.获得命令帮助的方法 ...

  9. 前后端分离,简单JWT登录详解

    前后端分离,简单JWT登录详解 目录 前后端分离,简单JWT登录详解 JWT登录流程 1. 用户认证处理 2. 前端登录 3. 前端请求处理 4. 后端请求处理 5. 前端页面跳转处理 6. 退出登录 ...

随机推荐

  1. 常用python机器学习库总结

    开始学习Python,之后渐渐成为我学习工作中的第一辅助脚本语言,虽然开发语言是Java,但平时的很多文本数据处理任务都交给了Python.这些年来,接触和使用了很多Python工具包,特别是在文本处 ...

  2. 解惑spring嵌套事物

    工作中一直对spring中的事物管理都是最简单的配置 但是spring中的事物传播性配置 还有很多种,有时候经常疑惑service调用service的问题,今天的论坛上看到一篇写的非常详细的文字.记录 ...

  3. git 设置代理服务器

    git可以通过以下命令设置代理服务器 git config --global http.proxy http://proxyuser:proxypwd@proxy.server.com:proxypo ...

  4. 【转帖】分享一个迅为4412开发板OTG烧录批处理文件

    平台:iTOP-4412开发板 Bat 功能: 1.可以分条的执行烧录,不需要每次烧录都去复制命令 2.可以批量烧录 开发板系统烧录批处理文件,请将此文件放置在fastboot程序同目录下,下载地址: ...

  5. linux学习(2)

    自从安装了虚拟机和各种工具软件之后,学习Linux的过程不断被打断,一直想把Ubuntu烧录到itop4412开发板里面去,却总是失败,感觉这个过程都加强我的抗打击能力了,现在来说说,对于一个第一次烧 ...

  6. 我的CentOS 7 U盘安装之路 (Win 8.1 Profession + CentOS 7双系统)

    这次为了学习Linux,尝试着安装了鸟哥书上推荐的CentOS这款Distribution,但是安装的是最新版CentOS 7,好像跟书上的差别有点大呢.安装的过程中走了一些弯路,做了一些尝试最后发现 ...

  7. BZOJ1500: [NOI2005]维修数列[splay ***]

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 12278  Solved: 3880[Submit][Statu ...

  8. 浅谈微信小程序

    在如火如荼的互联网技术发展中,各种各样的框架出现,当下最受关注的应该就是微信小程序了.从新闻论坛乃至qq群.微信群,很多很多从事IT工作的朋友喜欢讨论研究这个小程序.带着好奇心,我也参与其中. 第一步 ...

  9. Android BLE 蓝牙编程(四)

    接上篇,我们已经实现了短震,长震的功能了- 现在我们需要实现点击后一直震动的功能 开始我的想法是再循环中不断执行write方法,然而这个办法行不通. 系统会报错. 那要如何实现这个想法呢?其实很简单, ...

  10. smarty下如何将一个数保存为两位小数

    smarty模板是一种缓存技术,下面介绍一下smarty string_format用法 取小数点后2位: 用法如下: //index.php$smarty = new Smarty; $smarty ...