验证和授权在页面需要限制访问时用到。验证就是确认某人就是他所声称的那个人。通常涉及到用户名和密码,但也包含其他方式,例如智能卡,指纹等。授权是在验证用户后,查明他是否被允许管理指定的资源。通常判断他是否是有权访问资源的角色的成员。

Yii 有一个内置的验证/授权框架,它易于使用且可定制。

Yii 认证框架的核心是预声明的用户组件,它是一个实现 IWebUser 接口的对象。用户组件代表了当前用户的持久身份信息。可以使用 Yii::app()->user 来访问。

使用用户组件,可以使用 CWebUser::isGuest 检查一个用户是否已经登录;我们可以登录或者注销一个用户; 调用 CWebUser::checkAccess 可以检查用户是否可以执行特定的操作; 也可以得到用户的唯一身份和另外的持久身份信息。

定义身份类

如之前所说, 验证是确认用户的身份。典型的网络应用验证通常是使用用户名和密码的组合来确认用户的身份。然而,也可以包含其他的方法。为了掩饰兼容各种验证方法, Yii 认证框架引入了身份类。

我们定义一个身份类,它含有实际的验证逻辑。身份类应当实现 IUserIdentity 接口。不同的身份类可以实现不同的验证方法 (例如 OpenID, LDAP, Twitter OAuth, Facebook Connect). 推荐扩展 CUserIdentity 编写你自己的类,CUserIdentity 是使用用户名和密码这种验证方法的基类。

定义身份类最主要的工作是实现 [IUserIdentity::authenticate] 方法. 这个方法封装了验证的逻辑细节。在身份类中也可以声明额外的身份信息。

例子
在下面的例子中,我们使用一个身份类来演示使用数据库方法来验证。这是非常典型的方法。用户需要输入用户名和密码到登录表单中,然后我们验证这些账号信息,使用 ActiveRecord ,向数据库中的表来查询。我们需要演示的是

  • 实现 authenticate() 方法来根据数据库验证账号信息.
  • 重写 CUserIdentity::getId() 方法来返回 _id 属性,因为默认返回用户名作为 ID.
  • 使用 setState() (CBaseUserIdentity::setState) 方法来演示储存其他信息,这些信息可以在随后的访问被轻松获取
<?php
class UserIdentity extends CUserIdentity
{
private $_id;
public function authenticate()
{
$record=User::model()->findByAttributes(array('username'=>$this->username));
if($record===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if($record->password!==md5($this->password))
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
$this->_id=$record->id;
$this->setState('title', $record->title);
$this->errorCode=self::ERROR_NONE;
}
return !$this->errorCode;
}

public function getId()
{
return $this->_id;
}
}
?>

下个小结的登录和注销中,我们将看到把这个身份类放在用户的登录方法中。任何储存在状态中的信息 (使用 CBaseUserIdentity::setState) 将被传递给 CWebUser, 它们被保存到持久存储中,例如 session. 这些信息可以作为 CWebUser 的属性被访问。在我们的例子汇总,使用 $this->setState(‘title’,$record->title) 存储用户 title 信息. 在登录完成之后,可以使用 Yii::app()->user->title 得到当前用户的 title 信息。

信息: CWebUser 默认使用 session 作为用户身份信息的持久存储方式。若启用了基于 cookie 的登录 (通过设置 CWebUser::allowAutoLogin 为 true), 用户身份也可以被保存在 cookie 中。一定不要声明敏感信息 (例如密码) 为 persistent.

登录和注销

现在已经看到了创建一个用户身份的例子,我们使用它来简化登录和注销动作。如下代码展示了它们如何被实现的:

<?php
// Login a user with the provided username and password.
$identity=new UserIdentity($username,$password);
if($identity->authenticate())
Yii::app()->user->login($identity);
else
echo $identity->errorMessage;
......
// Logout the current user
Yii::app()->user->logout();
?>

这里我们创建了一个 UserIdentity 对象并传递账号信息 (也就是用户提交的 $username 和 $password ) 到它的构造器中. 然后我们只需调用 authenticate() 方法. 若成功,传递身份信息到 CWebUser::login 方法,在此方法中身份信息被存储到持久存储 (默认是 PHP session ) . 若验证失败, 我们可以查询 errorMessage 属性来了解为何失败.

判断一个用户是否登录非常简单,使用 Yii::app()->user->isGuest 即可. 若使用持久存储如 session (默认地) 和/或 cookie (下面讨论) 来存储身份信息, 用户在随后的请求中保持已登录状态. 这样,我们无需为每次请求使用 UserIdentity 类和完整的登录验证. CWebUser 将自动从持久存储中载入身份信息,用它们来检测Yii::app()->user->isGuest 返回的是 true 还是 false.

基于 cookie 的登录

默认情况下, 用户在一段闲置期限后将被注销, 取决于 session 配额. 为了改变这个行为, 我们可以设置 user 组件的 allowAutoLogin 属性为 true 并传递 duration 参数到 CWebUser::login 方法中. 在指定的期限内用户仍然处于登录状态,即使他关闭了浏览器窗口 注意此特征需要用户的浏览器接受 cookie.

<?php
// Keep the user logged in for 7 days.
// Make sure allowAutoLogin is set true for the user component.
Yii::app()->user->login($identity,3600*24*7);
?>

如之前所述,当启用了基于 cookie 的登录, 通过 CBaseUserIdentity::setState 存储的状态将也保存在 cookie 中. 下次用户登录时, 这些状态从 cookie 中读取,并且可以使用 Yii::app()->user 来访问。

虽然 Yii 有方法来防止状态 cookie 在客户端被篡改, 我们强烈建议安全敏感信息不要储存为状态. 而是选择存储在服务器端,从服务器端的持久存储中读取 (例如数据库).

此外, 位于要求较高的网络应用,我们建议使用如下策略来增强基于 cookie 登录的安全性:

  • 当用户填写登录表单后成功登录, 在 cookie 状态和服务器端的持久存储(如数据库)中生成并存储一个随机 key .
  • 在随后的访问中, 当通过 cookie 信息实现验证后, 我们对比这两个随机 key 来确保登录前他们是一致的。
  • 若用户通过表单再次登录, key 需要重新生成.

通过使用上面的策略, 我们消除了这种可能性:一个用户可以重新使用旧的包含过期 state 信息的 state cookie。

为了实现上面的策略, 我们需要重写如下两个方法:

    • CUserIdentity::authenticate(): 这里是认证真正执行的地方. 若用户被认证, 我们应当重新生成一个新的随机 key, 并把它存储到数据库以及身份状态中( 通过CBaseUserIdentity::setState).
    • CWebUser::beforeLogin(): 它在用户登录时被调用. 我们应当检查 state cookie 中的 key 是否和数据库中的是相同的

在下面的例子中,我们使用一个身份类来演示使用数据库方法来验证。这是非常典型的方法。用户需要输入用户名和密码到登录表单中,然后我们验证这些账号信息,使用 ActiveRecord ,向数据库中的表来查询。我们需要演示的是

  • 实现 authenticate() 方法来根据数据库验证账号信息.
  • 重写 CUserIdentity::getId() 方法来返回 _id 属性,因为默认返回用户名作为 ID.
  • 使用 setState() (CBaseUserIdentity::setState) 方法来演示储存其他信息,这些信息可以在随后的访问被轻松获取

<?php
class UserIdentity extends CUserIdentity
{
    private $_id;
    public function authenticate()
    {
        $record=User::model()->findByAttributes(array('username'=>$this->username));
        if($record===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        else if($record->password!==md5($this->password))
            $this->errorCode=self::ERROR_PASSWORD_INVALID;
        else
        {
            $this->_id=$record->id;
            $this->setState('title', $record->title);
            $this->errorCode=self::ERROR_NONE;
        }
        return !$this->errorCode;
    }

public function getId()
    {
        return $this->_id;
    }
}
?>

Yii入门,登录的更多相关文章

  1. yii自动登录

    在yii,登录页面选择记住密码,下次就会自动登陆 前些天,自己增加了一个web应用,但是发现虽然选择记住密码,没选退出,关闭浏览器,重新进入还会跳转到登陆页面 自动登录是利用cookie实现的 配置U ...

  2. yii中登录后跳转回登录前请求的页面

    当我们请求一个经过权限控制的请求不通过时,会跳转到一个地方请求权限,请求结束后需要跳转回之前的页面.比如我们请求一个需要登录的action,会被跳转到login页面,我们希望登录成功后跳转到我们之前希 ...

  3. 【YII】Yii入门

    1. 入门博客 http://blog.csdn.net/zm2714/article/category/1359776/2 2. 创建运行demo http://blog.csdn.net/zhou ...

  4. yii 用户登录验证(cwebuser) yii 用户登录 (记)

    yii 的确是一个强大而臃肿的框架,简单的小项目,或者只做后台接口调用的项目,建议不要用. 今天记录一下yii使用中cwebuser(Yii::app()->user->login())登 ...

  5. Yii入门☞应用

    Yii 应用的静态结构 应用: require可以有返回值,Yii中经常返回数组用以配置.以前只知道引用文件成功返回1. controllerMap属性允许你指定一个控制器ID到任意控制器类,修改配置 ...

  6. Yii入门教程

    1准备Yii源码 首先新建helloyii目录作为Web应用的根目录,并添加到Nginx的配置文件中.然后将Yii框架源码部署到helloyii下,目录结构如下: helloyii/ |-- fram ...

  7. php爬虫入门 - 登录抓取内容

    PHP 写爬虫 说实话我也想用Python的,毕竟人家招牌.无奈我Python还停留在看语法的阶段,实在太惭愧,鞭笞一下自己加油学习.这里用php的CURL库进行页面抓取. 同事使用的系统需要先登录, ...

  8. Yii 用户登录验证

    http://blog.sina.com.cn/s/blog_685213e70101mo4i.html 1)首先在model文件夹中新建文件 LoginForm.php 代码如下 <?php ...

  9. Yii 入门

    跳转到不同module Redirect to module after login Yii $this->redirect( array('/tradesman/default/index') ...

随机推荐

  1. LightOj 1245 --- Harmonic Number (II)找规律

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1245 题意就是求 n/i (1<=i<=n) 的取整的和这就是到找规律的题 ...

  2. 如何在Java客户端调用RESTful服务

    在这个例子中,我们将看到如何使用java.net包实用工具,创建一个访问REST服务RESTful的客户端.当然这不是创建一个RESTful客户端最简单的方法,因为你必须自己读取服务器端的响应,以及J ...

  3. 获取CentOS系统详情的九个uname命令实例

    当你在控制台模式下,无法通过“鼠标右键 > 关于”获取操作系统的信息.这时,在Linux下,你可以使用uname命令,帮助你完成这些工作. Uname是unix name的缩写.在控制台中实际使 ...

  4. Fiddler如何抓取使用了SSL或TLS传输的Android App流量

    上篇文章介绍了Burpsuite如何抓取使用了SSL或TLS传输的Android App流量, 那么使用Fiddler的时候其实 也会出现与burpsuite同样的情况,解决方案同样是需要将Fiddl ...

  5. Data Flow ->> OLE Command

    这里有篇博客文章是讲这个OLE Command的:http://www.cnblogs.com/tylerdonet/archive/2011/06/20/2085490.html OLE Comma ...

  6. Mybatis SqlSessionTemplate 源码解析

    As you may already know, to use MyBatis with Spring you need at least an SqlSessionFactory and at le ...

  7. Android与OpenCV——重新下载安装和OpenCV匹配的Android开发环境

    Android与OpenCV——重新下载安装和OpenCV匹配的Android开发环境 !!OpenCV4Android开发之旅(一)----OpenCV2.4简介及 app通过Java接口调用Ope ...

  8. sysfs - 用于导出内核对象(kobject)的文件系统

    sysfs - _The_ filesystem for exporting kernel objects.sysfs - 用于导出内核对象(kobject)的文件系统Patrick Mochel & ...

  9. BZOJ 2038 小Z的袜子(hose)(分组)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2038 题意:给出n个袜子.m个询问,每个询问一个区间[L,R],询问这个区间中任意拿出两 ...

  10. [Golang] base64加密与解密

    首先解释以下什么是base64(来自百度百科): Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045-RFC2049,上面有MIME的详细规范.Base64 ...