Yii2의 시나리오 및 검증 규칙에 대한 자세한 설명

jacklove
풀어 주다: 2023-04-02 08:06:01
원래의
3877명이 탐색했습니다.

Yii2의 규칙은 모델 속성을 검증하는 데 사용됩니다. 시나리오 사용자는 다양한 시나리오에서 검증해야 하는 모델을 정의합니다. 다음 글에서는 Yii2의 시나리오(시나리오) 및 검증 규칙(규칙)에 대한 관련 정보를 주로 소개합니다. . 기사에는 샘플 코드를 통한 소개가 매우 자세하게 나와 있어 도움이 필요한 친구들이 참고할 수 있습니다.

머리말

Scene은 이름에서 알 수 있듯이 상황, 장면입니다. Yii2에는 여러분이 이해하는 장면과 비슷한 의미를 갖는 장면도 있습니다.

사용자와 상호작용하는 시스템의 필수 기능에는 사용자 데이터 수집, 검증 및 처리가 포함됩니다. 실제 비즈니스에서는 데이터를 지속적으로 저장해야 하는 경우가 많습니다. 보안상의 이유로 개발자는 "클라이언트의 입력은 신뢰할 수 없다"는 원칙을 확실히 이해해야 합니다. 클라이언트가 전달한 데이터는 내부 시스템에 저장되거나 전송되기 전에 필터링되고 정리됩니다.

Yii2에서는 사용자 데이터를 수집하고 확인하기 위해 Model 클래스를 사용할 것을 권장하며, 영구 ActiveRecord 클래스는 해당 하위 클래스입니다. Model 클래스의 load 및 verify 메서드는 각각 클라이언트 데이터를 수집하고 확인하는 데 사용됩니다. 어떤 데이터를 수집해야 하고 어떤 데이터를 검증해야 하는지 이 글의 주제는 어떤 시나리오입니다: 시나리오와 검증 규칙.

아래에는 별로 할 말이 없지만, 편집자의 설명을 따라가며 자세한 소개를 살펴보겠습니다.

시스템 구조

먼저 간단한 비즈니스 시스템을 소개합니다. 시스템에는 학생과 교사의 두 가지 역할이 있으며 역할 정보를 저장하기 위해 데이터베이스에서 세 개의 테이블이 사용됩니다:

사용자: [id, 사용자 이름, 비밀번호, 상태, 기타 공통 속성]

student: [id, user_id, Student_no, grade, class, 기타 학생 속성]

teacher: [id, user_id, work_no, title, 전화, 기타 교사 속성]

실제 업무는 이 세 테이블의 추가, 삭제, 쿼리, 수정 작업에 국한되지 않습니다. 문제를 단순화하기 위해 나중에 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 클래스의 규칙 메서드를 빠르게 작성할 수 있다고 믿습니다. 예를 들어 User 클래스 파일의 내용은 다음과 같을 수 있습니다.

namespace app\models;
class User extends \yii\db\ActiveRecord
{
 public function rules()
 {
  return [   [["username", "password", "status",], "required"],
   ["username", "unique"],
   // other rules
  ];
 }
 // other method
}
로그인 후 복사

데이터에 대한 유효성 검사 규칙을 정의합니다. 이는 대부분의 사람들이 규칙에 대해 갖는 첫인상이며 좋은 인상입니다. 불법 데이터를 정상적인 데이터로 만들어 시스템에 입력합니다. 보안 관행은 완전한 규칙을 정의하고 데이터를 완전히 검증하도록 노력해야 합니다. 또한 모든 Yii2 개발자는 내장된 핵심 유효성 검사기에 익숙해지는 것이 좋습니다.

정보 수정

정보 수정도 일반적인 추가, 삭제, 확인, 수정 작업입니다. 구현 코드와 등록에는 큰 차이가 없습니다. 여기서는 두 가지 사항만 논의합니다.

1. 사용자 비밀번호 확인

등록 시 사용자 비밀번호가 8~16자리인지 확인됩니다. 규칙은 다음과 같습니다: ["password", "string", "length" => [8, 16]] . 비밀번호를 일반 텍스트로 저장하는 것은 바람직하지 않습니다. 데이터베이스에 삽입할 때 최소한 MD5 암호화가 수행되고 비밀번호는 32비트가 됩니다. 사용자가 정보 수정 시 비밀번호를 변경하지 않았다고 가정하고 다시 저장하면 비밀번호 규칙 확인 오류가 발생하여(길이가 일치하지 않음) 저장할 수 없습니다! ["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)

이 문제를 해결하는 방법은 무엇입니까? Yii 문서를 살펴보면서 규칙의 when 속성이 도움이 될 수 있다는 것을 발견했습니다. 가능한 확인 규칙 중 하나는 다음과 같습니다.

unset($data["password"]); 
$user->load($data);
// 或者
$password = $user->password;
$user->load($data);
$user->password = $password;
로그인 후 복사

등록(새 데이터)할 때만 비밀번호 필드를 확인하세요. 문제가 해결되었습니다. 완벽해요!

2. 사용자가 비공개로 비밀번호를 변경하지 못하도록 방지

🎜🎜 시스템이 Yii 프레임워크를 사용하여 구축되었음을 발견하고 자신의 기술을 과시하기 위해 약간의 피해를 입히고 싶어하는 똑똑한 사람(예: Tom)이 있다고 가정해 보겠습니다. 정보를 수정하기 위해 양식을 보낼 때 Tom은 &password=12345678을 추가합니다. 시스템은 $user->load($data)를 사용하여 사용자 입력을 수집하고 비밀번호 필드를 업데이트합니다. 이로 인해 다음과 같은 결과가 발생합니다. 규칙 설정이 업데이트될 때 비밀번호 필드가 확인되지 않습니다. 12345678은 데이터베이스에 비밀번호 값으로 직접 저장됩니다. 이 작업은 연쇄 반응을 일으켰습니다. 사용자가 다시 로그인했을 때 암호화된 비밀번호가 데이터베이스의 일반 텍스트 비밀번호와 일치하지 않아 Tom이 시스템에 로그인할 수 없게 되었습니다. 짜증나는 점은 톰이 로그인이 안된 후 하루종일 고객센터를 괴롭힌다는 것인데 그게 쉽지 않더라구요! 🎜🎜이런 상황이 발생하지 않도록 하려면 어떻게 해야 하나요? 한 가지 해결책은 비밀번호 변경을 방지하는 것입니다. 🎜🎜🎜
$form = new UpdateInfoForm();
$form->load($data);
if ($form->validate()) {
 $user->load($form->attributes);
 $student->load($form->attributes);
 // next biz
}
로그인 후 복사
로그인 후 복사
🎜🎜🎜 사용자가 입력한 비밀번호를 필터링하면 비공개로 비밀번호를 변경하는 문제가 해결됩니다. 🎜🎜하지만 문제는 아직 끝나지 않았습니다. Tom은 성별, 신분증 등과 같은 다른 필드를 수정할 수 있습니다. 더 심각한 상황은 학생의 user_id를 수정하면 모든 학생의 정보를 변경할 수 있다는 것입니다. 문제는 심각하므로 취약점을 즉시 수정해야 합니다. 🎜

可以按照密码的方法,逐个屏蔽受保护属性,但显得啰嗦难看(虽然好使)。如果受保护属性多,可以仅允许白名单进入,具体操作为:新增一个UpdateInfoForm类继承Model,属性是白名单属性合计。用UpdateInfoForm类过滤用户数据,校验通过后再更新到user和student中:

$form = new UpdateInfoForm();
$form->load($data);
if ($form->validate()) {
 $user->load($form->attributes);
 $student->load($form->attributes);
 // next biz
}
로그인 후 복사
로그인 후 복사

这种方式更优雅,但仔细一想代价不小:属性和验证规则要重复写一遍;user和student保存时又重复校验属性。这种方式看起来优雅,实际上却冗余又低效。

scenario的登场,完美的解决解决上述问题。

场景(scenario)

分析上面问题,会发现关键点是批量赋值(massive assignment)和数据校验(validate)两个方法。如果对不同的场景指定赋值字段和检验规则,问题就迎刃而解。

Yii中的scenario有 安全属性 和 活跃属性 两个概念。安全属性用在批量赋值的load方法,只有安全属性才能被赋值;活跃属性用在规则校验的validate方法,在活跃属性集中并且定义了校验规则的属性才会被校验。活跃属性和安全属性的关系是,安全属性是活跃属性的子集。

\yii\base\Model类定义了默认场景:SCENARIO_DEFAULT(值为default)。默认场景下,出现在rules方法中的属性既是活跃属性,又是安全属性(这句话基本正确,看后续解释)。为不同场景指定活跃属性、安全属性以及校验器,可以通过覆盖senarios或rules两个方法实现(几乎每个Model类都会重写rules方法,senarios用得少)。

rules

先看rules方法。默认的属性加校验器定义方式,让每个属性既是安全属性,也是活跃属性。如果想让某个属性不是安全属性(不能通过load批量赋值),在属性名前加感叹号!即可。例如student中的user_id字段:

public function rules()
{
 return [
  ["!user_od", "required"],
  ["!user_id", "integer"],
  ["!user_od", "unique"],
  // other rules
 ];
}
로그인 후 복사

user_id是活跃属性,在写入数据库时会被校验。但它不是安全属性,不能通过load方法进行赋值,解决了安全隐患。

再看rules方法按场景区分校验器规则的做法:定义校验器时on属性指定规则在哪些场景下生效,except属性则排除一些场景(如果不指定on和except,规则对所有场景生效)。例如:

public function rules()
{
 return [
  ["password", "string", "length" => [8, 16], "on" => ["signup"]], // 仅在signup场景时才被验证
  ["status", "integer", "except" => ["signup"], // 除了signup场景,其他情况都校验
  // other rules
 ];
}
로그인 후 복사

在原来基础上新增感叹号和on/except属性,非常简便的就定义了非安全属性以及分场景指定校验规则。

scenarios

另外一种更清晰定义安全属性和活跃属性的做法是重写scenarios方法。scenarios方法返回一个数组,数组的键是场景名称,值是活跃属性集合(包饭安全属性)。例如student表的可能实现如下:

public function scenarios()
{
 return [
  self::SCENARIO_DEFAULT => ["!user_id", "grade", "class", xxxx],
  "update" => ["grade", "class", xxxx],
 ];
}
로그인 후 복사

默认情形下(学生报名),年级、班级这些信息是安全属性,但user_id不是,只能在程序内部赋值,并在插入数据时被校验;在修改信息时,user_id不是活跃属性,既不能被批量赋值,也不需要校验(事实上它不应该改变)。

scenarios方法只能定义活跃属性和安全属性,无法定义校验规则,需要和rules配合使用。

总结

金肯定义完善的数据校验规则

业务复杂时定义多个场景,仔细为每个场景定义安全属性和校验规则

优先使用rules;属性较多、rules复杂时,可以配合scenarios方法迅速理清安全属性和活跃属性

参考

http://www.yiiframework.com/doc-2.0/guide-input-validation.html

您可能感兴趣的文章:

MixPHP、Yii和CodeIgniter的并发压力测试的小结

PHP基于非递归算法实现先序、中序及后序遍历二叉树操作的示例

PHP使用两个栈实现队列功能的方法的讲解

위 내용은 Yii2의 시나리오 및 검증 규칙에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!