前言
場景,顧名思義,就是一個情景,一種場面。在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,就可以更改任意學生的信息。事情十分嚴重,需要馬上修復漏洞。
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。
新聞熱點
疑難解答