首页 > 编程 > PHP > 正文

Yii2中的场景(scenario)和验证规则(rule)的详解

2020-03-22 19:05:50
字体:
来源:转载
供稿:网友
Yii2的rule用于对模型属性进行验证,scenario用户定义不同场景下需要验证的模型,下面这篇文章主要给大家介绍了关于Yii2中场景(scenario)和验证规则(rule)的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。

前言

场景,顾名思义,就是一个情景,一种场面。在yii2中也有场景,这个场景跟你所理解的场景含义差不多。

和用户有交互的系统必不可少的功能包括收集用户数据、校验和处理。实际业务中,往往还需要将数据进行持久化存储。出于安全考虑,开发人员应当牢牢把握“客户端的输入都是不可信”的准则,客户端传过来的数据先进行过滤和清洗后再存储或传递到内部系统。

Yii2推荐使用Model类来收集和校验用户数据,持久化的ActiveRecord类是其子类。Model类的load和validate两个方法,分别用来收集和校验客户端数据。哪些数据应该被收集,哪些数据需要在什么场景下验证,便是本文的主题:场景(scenario)和验证规则(rule)。

下面话不多说了,来随着小编一起看看详细的介绍吧。

系统结构

先引入一个简单的业务系统:系统中存在学生和教师两种角色,数据库中使用了三张表保存角色信息:

user: [id, username, password, status, 其他通用属性]

student: [id, user_id, student_no, grade, html' target='_blank'>class, 其他学生属性]

teacher: [id, user_id, work_no, title, telphone, 其他教师属性]

实际业务不限于对这三张表的增删查改操作。为了简化问题,后续仅讨论user和student两张表的数据变更(给出teacher表是为了让读者不认为设计数据库的人是脑残:明明可以放到一张表的,为什么要拆开!)。

学生报名

学生报名是典型的增删查改操作,送分题。学生报名的简要代码示例如下:

public function actionSignup() $data = Yii::$app- request- post(); $user = new User(); $user- load($data); if ($user- save()) { $student = new Student([ user_id = $user- id, $student- load($data); if ($student- save()) { // redirect to success page } else { $user- delete(); // render error page}

相信有Yii2使用经验的人都能根据数据库的字段约束快速的把User和Student类的rules方法写出来。例如User类文件内容可能如下:

namespace app/models;class User extends /yii/db/ActiveRecord public function rules() return [ [[ username , password , status ,], required ], [ username , unique ], // other rules // other method}

定义数据的验证规则,这是大多数人对rules的第一印象,并且是一个很好的印象:它打回非法的数据,让正常的数据进入系统中。安全的实践应该尽量定义完整的规则,充分验证数据。也建议每一个Yii2开发人员对内置的核心校验器熟悉。

修改信息

修改信息,也是典型的增删查改操作。实现代码和报名差别不大,这里仅讨论两点:

1、用户密码的验证

注册时会校验用户密码是否8-16位,密码的规则可能是: [ password , string , length = [8, 16]] 。明文保存密码是不可取的,插入数据库时至少会做MD5加密,password变成32位。假设用户修改信息时未修改密码,再次保存时密码规则校验出错(长度不符合),无法保存!

怎么解决这个问题呢?翻阅Yii文档,发现了规则中的when属性可以救场。一种可能的验证规则是:

public function rules() return [ [ password , string , length = [8, 16], when = function ($model) { return $model- isNewRecord; // other rules ];

只有在注册(新增数据)时才校验密码字段。问题解决,完美!

2、防止用户私自改密码

假设有个小聪明的家伙(例如汤姆),发现系统是用Yii框架做的,想搞点小破坏炫耀一下水平。在发送修改信息的表单时,汤姆增加 password=12345678这一段数据。系统使用$user- load($data)收集用户输入,更新password字段,带来如下后果:rules设置更新时不校验密码字段,12345678直接作为password的值保存到数据库中。这个操作带来连锁反应:用户再次登录时,加密过后的密码与数据库中的明文密码不匹配,导致汤姆无法登录系统。烦人的是汤姆是个刺头,登录不上后整天骚扰客服,不省心!

怎么样防止这种情况出现呢?一种解决的方法是阻止修改密码:

unset($data[ password ]); $user- load($data);// 或者$password = $user- password;$user- load($data);$user- password = $password;

把用户输入的密码过滤掉,私自修改密码的问题就解决了。

但是问题还没有结束:汤姆可以转向修改其他字段,比如说性别,身份证等。更严重情况是修改student中user_id,就可以更改任意学生的信息。事情十分严重,需要马上修复漏洞。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表