Scenario (scenario) and verification Rules (rule) in Yii2, yii2scenario
Preface
A scenario, as its name implies, is a scene. There are also scenarios in yii2, which are similar to what you understand.
Systems that interact with users are essential to collect user data, verify and process user data. In actual business scenarios, data needs to be stored persistently. For security reasons, developers should firmly grasp the principle that "client input is untrusted". The data transmitted from the client is filtered and cleaned before being stored or transmitted to the internal system.
In Yii2, we recommend that you use the Model class to collect and verify user data. The persistent ActiveRecord class is its subclass. The load and validate methods of the Model class are used to collect and verify client data respectively. The topic of this article is the scenario (scenario) and validation rule (rule ).
I will not talk about it much below. Let's take a look at the detailed introduction with xiaobian.
System Structure
First, introduce a simple business system: There are two roles in the system: student and teacher. The database uses three tables to save the role information:
User: [id, username, password, status, other common attributes]
Student: [id, user_id, student_no, grade, class, other student attributes]
Teacher: [id, user_id, work_no, title, telphone, other instructor attributes]
The actual business is not limited to adding, deleting, querying, and modifying the three tables. In order to simplify the problem, we will discuss only the data changes of the user and student tables in the future (the teacher table is given so that the reader does not think that the database design is brainless: It can be placed in one table, why do you want to split it !).
Student registration
Student registration is a typical addition, deletion, query, and modification operation to deliver questions. The following is a brief code example for student registration:
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}
I believe that anyone with Yii2 experience can quickly write the rules methods of the User and Student classes according to the field constraints of the database. For example, the content of a User file may be as follows:
namespace app\models;class User extends \yii\db\ActiveRecord{ public function rules() { return [ [["username", "password", "status",], "required"], ["username", "unique"], // other rules ]; } // other method}
Defining data validation rules is the first impression of most people on rules and a good impression: it calls back illegal data to let normal data into the system. Security Practices should try to define complete rules to fully verify data. We recommend that every Yii2 developer be familiar with the built-in core checker.
Modify Information
Modification information is also a typical addition, deletion, query, modification operation. The implementation code is slightly different from the registration code. Here we only discuss two points:
1. User Password Verification
During registration, the system checks whether the user's password is 8-16 characters long. The password rules may be:["password", "string", "length" => [8, 16]]
. The plaintext password cannot be obtained. At least MD5 encryption is performed during database insertion, And the password becomes 32-bit. Assume that the password is not modified when the user modifies the information. When the password is retained, the verification of the password rule is incorrect (the length does not match) and cannot be saved!
How can this problem be solved? Read the Yii document and find that the when attribute in the rule can be saved. One possible verification rule is:
public function rules(){ return [ ["password", "string", "length" => [8, 16], 'when' => function ($model) { return $model->isNewRecord; }], // other rules ];
The password field is verified only when you register (add data. Problem solving, perfect!
2. Prevent Unauthorized Password Change
Suppose there is a clever guy (such as Tom) who finds that the system is built on the Yii framework and wants to make some small damage to show off its level. Tom added the & password = 12345678 section of data when sending the form for modification information. System usage$user->load($data)
Collect User input and update the password field, causing the following consequences: When rules is set, the password field is not verified, and 12345678 is directly saved to the database as the password value. This operation leads to a chain reaction: when a user logs on again, the encrypted password does not match the plaintext password in the database, and Tom cannot log on to the system. What's annoying is that Tom is a spider. After login, Tom harasses customer service all day and is not worried!
How can this problem be prevented? One solution is to prevent password modification:
Unset ($ data ["password"]); $ user-> load ($ data); // or $ password = $ user-> password; $ user-> load ($ data); $ user-> password = $ password;
The password entered by the user is filtered out, and the problem of private password modification is solved.
But the problem is not over yet: Tom can switch to other fields, such as gender and ID card. More seriously, you can modify the user_id in student to modify the information of any student. The problem is very serious. You need to fix the vulnerability immediately.
You can use the password method to block the protected attributes one by one, but it looks ugly (although good ). If there are many protected attributes, you can only allow access to the whitelist. The specific operation is to add an UpdateInfoForm class to inherit the Model. The attribute is the total of the whitelist attributes. Use the UpdateInfoForm class to filter user data and update it to the user and student after the verification is passed:
$form = new UpdateInfoForm();$form->load($data);if ($form->validate()) { $user->load($form->attributes); $student->load($form->attributes); // next biz}
This method is more elegant, but the cost is not small: the attributes and verification rules should be repeated; the user and student verify the attributes again when they are saved. This method looks elegant, but is actually redundant and inefficient.
The appearance of scenario perfectly solves the above problems.
Scenario (scenario)
After analyzing the problem above, we will find that the key points are the massive assignment and data verification (validate) methods. If you specify a value field and validation rule for different scenarios, the problem is solved.
Scenario in Yii has two concepts: security attributes and active attributes. Security attributes are used in the load method of batch assignment. Only security attributes can be assigned values. Active attributes are used in the validate method of Rule validation, in the active Attribute Set and the validation rule is defined, the attribute is verified. The relationship between active attributes and security attributes is that security attributes are a subset of active attributes.
The \ yii \ base \ Model class defines the default scenario: SCENARIO_DEFAULT (value: default ). By default, attributes in the rules method are both active and security attributes (this sentence is basically correct and can be explained later ). You can specify active attributes, security attributes, and validators for different scenarios by overwriting senarios or rules (almost every Model class will override the rules method, and senarios is rarely used ).
Rules
First look at the rules method. The default attribute-based validator defines each attribute as both a Security Attribute and an active attribute. If you want to make an attribute not a Security Attribute (you cannot assign values in batches through load), add an exclamation point before the attribute name! You can. For example, the user_id field in student:
public function rules(){ return [ ["!user_od", "required"], ["!user_id", "integer"], ["!user_od", "unique"], // other rules ];}
User_id is an active attribute and is verified when being written to the database. However, it is not a Security Attribute and cannot be assigned a value through the load method, solving the security risk.
Let's look at the rules method to differentiate the validator rules by scenario: when defining the validator, The on Attribute specifies the scenario in which the rule takes effect, and the except T attribute will exclude some scenarios (if on and except T are not specified, rules apply to all scenarios ). For example:
Public function rules () {return [["password", "string", "length" => [8, 16], "on" => ["signup"], // ["status", "integer", "alarm t" => ["signup"] is verified only in the signup scenario. // in addition to the signup scenario, verify all other cases // other rules];}
The exclamation point and on/Login T attributes are added on the basis of the original one, which makes it easy to define non-security attributes and specify validation rules by scenario.
Scenarios
Another way to clearly define security attributes and active attributes is to rewrite the scenarios method. The scenarios method returns an array. The key of the array is the scene name, and the value is the set of active attributes (meal Security Attribute ). For example, the student table may be implemented as follows:
public function scenarios(){ return [ self::SCENARIO_DEFAULT => ["!user_id", "grade", "class", xxxx], "update" => ["grade", "class", xxxx], ];}
By default (student registration), the information of grade and class is a security attribute, but the user_id is not. It can only be assigned within the program and verified when data is inserted. when the information is modified, user_id is not an active attribute. It cannot be assigned values in batches or requires no verification (in fact, it should not be changed ).
The scenarios method can only define active and security attributes. validation rules cannot be defined and must be used with rules.
Summary
Ken defines comprehensive data verification rules
When the business is complex, multiple scenarios are defined, and security attributes and validation rules are carefully defined for each scenario.
Rules is preferred. When there are many attributes and complex rules, you can use scenarios to quickly clarify security attributes and active attributes.
Well, the above is all the content of this article. I hope the content of this article has some reference and learning value for everyone's learning or work. If you have any questions, please leave a message to us, thank you for your support.
Reference
Http://www.yiiframework.com/doc-2.0/guide-input-validation.html