摘要:原文來(lái)自上一篇文章講了用戶(hù)的注冊(cè),驗(yàn)證和登錄,這一篇文章按照約定來(lái)說(shuō)說(shuō)之中的用戶(hù)和權(quán)限控制。探尋上面的一些列設(shè)置和代碼更改,已經(jīng)實(shí)現(xiàn)了一小部分的用戶(hù)控制登錄的用戶(hù)才能發(fā)表。
原文來(lái)自: https://jellybool.com/post/programming-with-yii2-user-access-controls
上一篇文章講了用戶(hù)的注冊(cè),驗(yàn)證和登錄,這一篇文章按照約定來(lái)說(shuō)說(shuō)Yii2之中的用戶(hù)和權(quán)限控制。
你可以直接到Github下載源碼,以便可以跟上進(jìn)度,你也可以重頭開(kāi)始,一步一步按照這個(gè)教程來(lái)做。
鑒于本教材基于Yii2 Basic,所以對(duì)RBAC的詳細(xì)講解我后面再多帶帶出文章來(lái)說(shuō)說(shuō)吧,這里主要是簡(jiǎn)單地說(shuō)一說(shuō)權(quán)限控制
上一篇文章所實(shí)現(xiàn)的功能還比較簡(jiǎn)單,可以發(fā)一條狀態(tài),但是不知道你注意到?jīng)]有,如果是沒(méi)有注冊(cè)的用戶(hù)也可以使用我們的應(yīng)用(類(lèi)似小微博)來(lái)發(fā)狀態(tài),這是不符合情理的。正確的做法是在用戶(hù)沒(méi)有注冊(cè),登錄之前,我們甚至都不應(yīng)該給沒(méi)有注冊(cè)的用戶(hù)看到我們創(chuàng)建狀態(tài)的頁(yè)面,即是http://localhost:8999/status/create就不應(yīng)該讓游客看到,更不用說(shuō)編輯和刪除一條狀態(tài)(status)了。
權(quán)限控制什么是權(quán)限控制?個(gè)人覺(jué)得在一個(gè)Web應(yīng)用當(dāng)中,有以下幾種常見(jiàn)的角色和權(quán)限控制:
1. 游客,也就是沒(méi)有注冊(cè)的用戶(hù),一般這個(gè)權(quán)限是最小的,對(duì)于一些需要登錄訪(fǎng)問(wèn)的頁(yè)面沒(méi)有訪(fǎng)問(wèn)權(quán)限 2. 用戶(hù),這里的用戶(hù)特指注冊(cè)用戶(hù),注冊(cè)過(guò)后的用戶(hù)一般可以使用整個(gè)web應(yīng)用的主要功能,比如我們這里的發(fā)表一條狀態(tài)(status) 3. 作者,這個(gè)不知道確切應(yīng)該使用什么名詞來(lái)描述,作者是在用戶(hù)注冊(cè)之后的一個(gè)權(quán)限判斷,比如A發(fā)表的status狀態(tài),B君不能進(jìn)行編輯,刪除等,反之亦然。 4. 管理員,這里的管理員通常會(huì)是應(yīng)用的開(kāi)發(fā)者(所有者,或者應(yīng)該這么說(shuō)),幾乎可以說(shuō)是對(duì)站點(diǎn)的所有權(quán)限都有
Yii2自帶的權(quán)限控制默認(rèn)只支持兩個(gè)角色:
guest(游客,沒(méi)有登錄的,用?表示)
authenticated (登錄了的,用@表示)
在這里我們需要實(shí)現(xiàn)的是對(duì)這兩種不同的角色指定不同的訪(fǎng)問(wèn)權(quán)限,就是為他們分配不同的可以訪(fǎng)問(wèn)的控制器或者方法。
目前我們?nèi)绻苯狱c(diǎn)擊導(dǎo)航欄的Status,我們還是可以在沒(méi)有登錄的情況之下進(jìn)行發(fā)表狀態(tài)(status),所以我們需要改一下我們的代碼和邏輯,Yii2在這方面的控制做得非常好,其實(shí)實(shí)現(xiàn)這個(gè)我們只需要修改一下StatusController.php里面的behaviors()方法而已,在這里面加入一段access設(shè)置:
``` public function behaviors() { return [ "verbs" => [ "class" => VerbFilter::className(), "actions" => [ "delete" => ["post"], ], ], "access" => [ "class" => AccessControl::className(), "only" => ["index","create","update","view"], "rules" => [ // allow authenticated users [ "allow" => true, "roles" => ["@"], ], // everything else is denied ], ], ]; } ```
加上access這一段之后,我們?cè)俅吸c(diǎn)擊Status,Yii2就會(huì)將未登錄的我重定向到登錄頁(yè)面。
而且,這個(gè)時(shí)候,一旦你登入進(jìn)去,Yii會(huì)默認(rèn)自動(dòng)跳轉(zhuǎn)到上一個(gè)url,也就是我們剛剛點(diǎn)擊的status/index。
添加映射關(guān)系用戶(hù)一旦登錄進(jìn)來(lái)之后,我們就可以通過(guò)下面這行代碼來(lái)獲取用戶(hù)的id了:
``` Yii::$app->user->getId(); ```
一旦用戶(hù)的id獲取到,我們可以做的事就很多了。這里我們先來(lái)將一條狀態(tài)和用戶(hù)聯(lián)系起來(lái),也就是添加用戶(hù)與說(shuō)說(shuō)的映射關(guān)系。要實(shí)現(xiàn)這個(gè)目標(biāo)我們需要先修改我們的數(shù)據(jù)表(體驗(yàn)一下當(dāng)初設(shè)計(jì)數(shù)據(jù)表考慮不周全的情況):
``` ./yii migrate/create extend_status_table_for_created_by Yii Migration Tool (based on Yii v2.0.6) Create new migration "/Users/jellybool/Desktop/helloYii/migrations/m150806_034325_extend_status_table_for_created_by.php"? (yes|no) [no]:yes New migration created successfully. ```
打開(kāi)對(duì)應(yīng)的migration文件,編輯up()和down()方法,如果你想加入數(shù)據(jù)庫(kù)的事務(wù)管理功能,你可以使用safeUp()和safeDown()方法
``` public function up() { $this->addColumn("{{%status}}","created_by",Schema::TYPE_INTEGER." NOT NULL"); $this->addForeignKey("fk_status_created_by", "{{%status}}", "created_by", "{{%user}}", "id", "CASCADE", "CASCADE"); } public function down() { $this->dropForeignKey("fk_status_created_by","{{%status}}"); $this->dropColumn("{{%status}}","created_by"); } ```
我們需要為status表添加一個(gè)created_by字段,并且將它跟user表的id設(shè)為外鍵關(guān)系。
如果你在status表里面有一條數(shù)據(jù)記錄,你需要先刪除這一條記錄,不然可能會(huì)報(bào)錯(cuò)。
執(zhí)行migrate/up:
``` ./yii migrate/up Yii Migration Tool (based on Yii v2.0.6) Total 1 new migration to be applied: m150806_034325_extend_status_table_for_created_by Apply the above migration? (yes|no) [no]:yes *** applying m150806_034325_extend_status_table_for_created_by > add column created_by integer NOT NULL to table {{%status}} ... done (time: 0.032s) > add foreign key fk_status_created_by: {{%status}} (created_by) references {{%user}} (id) ... done (time: 0.014s) *** applied m150806_034325_extend_status_table_for_created_by (time: 0.059s) ```
數(shù)據(jù)表的外鍵設(shè)置好之后,我們就可以來(lái)聲明Status和User的關(guān)系了,不過(guò)在開(kāi)始之前需要修改一下User.php里面的內(nèi)容:
```直接將原來(lái)的User模型的代碼都刪掉,只需要我們上面的代碼就可以了,因?yàn)槲覀兪褂昧薡ii2-User,
這里就是使用dektriumusermodelsUser這個(gè)模型,然后修改一下我們的config/web.php,再我們之前的user中加入幾行代碼:``` "modules" => [ "user" => [ "class" => "dektriumuserModule", "confirmWithin" => 21600, // add the following 3 lines "modelMap" => [ "User" => "appmodelsUser", ], "cost" => 12, "admins" => ["admin"] ], ], ```這樣之后,我們的User和Status的對(duì)應(yīng)關(guān)系就會(huì)建立起來(lái)。
然后我們?cè)赟tatus.php寫(xiě)上以下的說(shuō)明:
``` public function getUser() { return $this->hasOne(User::className(), ["id" => "created_by"]); } ```這里聲明的映射關(guān)系為hasOne,也就是說(shuō),一條狀態(tài)status(說(shuō)說(shuō))對(duì)應(yīng)一個(gè)用戶(hù)(User),我們通過(guò)["id" => "created_by"]來(lái)指定外鍵映射。
有了Status和User的對(duì)應(yīng)關(guān)系之后,我們需要在用戶(hù)發(fā)表狀態(tài)的時(shí)候?qū)⒂脩?hù)的id保存到Status的created_by這一個(gè)字段中,所以我們需要在StatusController中的actionCreate方法中加上一行代碼:
``` if ($model->load(Yii::$app->request->post())) { $model->created_by = Yii::$app->user->getId();//add this line $model->created_at = time(); $model->updated_at = time(); if ($model->save()) { return $this->redirect(["view", "id" => $model->id]); } } ```這里需要確認(rèn)的是,你需要保證create方法只能是登錄進(jìn)來(lái)的用戶(hù)才能訪(fǎng)問(wèn)觸發(fā)。
為了更好地展示一條狀態(tài)stutas的信息,我們修改一下展示狀態(tài)的視圖文件:status/view.php :
``` = DetailView::widget([ "model" => $model, "attributes" => [ "id", "user.email", // add this line "message:ntext", "created_by", // add this line "permissions", "created_at", "updated_at", ], ]) ?> ```上面的user.email中的user其實(shí)是觸發(fā)Status::getUser()這個(gè)方法。
這樣一刷新之后,我們就可以看到創(chuàng)建這條狀態(tài)的用戶(hù)id和email了。
探尋RBAC上面的一些列設(shè)置和代碼更改,已經(jīng)實(shí)現(xiàn)了一小部分的用戶(hù)控制:登錄的用戶(hù)才能發(fā)表status。然而這還不能滿(mǎn)足我們?cè)谌粘J褂玫男枨?,比如我們現(xiàn)在怎么確定一個(gè)用戶(hù)能不能對(duì)某條狀態(tài)進(jìn)行修改和刪除?或者說(shuō),管理員的角色在哪里體現(xiàn)呢?現(xiàn)在貌似都是平等的角色,相同的權(quán)限,對(duì)于登錄的用戶(hù)來(lái)說(shuō)。
鑒于官方文檔或者很多關(guān)于Yii2 RBAC的資料都是基于Yii2 Advanced Template,而我們一開(kāi)始使用的是Yii2 Basic Template,并且我們也引入Yii2-User,所以這里我們嘗試來(lái)自己實(shí)現(xiàn)一點(diǎn)點(diǎn)的用戶(hù)權(quán)限控制。
首先我們需要在User中定義一些跟角色(role)相關(guān)的規(guī)定,比如根據(jù)不同的用戶(hù)角色來(lái)賦予不同的常量:
``` class User extends BaseUser { const ROLE_USER = 10; const ROLE_MODERATOR = 20; const ROLE_ADMIN = 30; } ```上面的代碼寫(xiě)在User模型里面,這里定義了三種角色,ROLE_USER,ROLE_MODERATOR,ROLE_ADMIN,USER可以發(fā)表狀態(tài),MODERATOR可以修改但是不可以刪除,ADMIN可以修改和刪除。
然后在helloYii/目錄之下創(chuàng)建一個(gè)components/目錄,里面新建一個(gè)AccessRule.php文件:
roles) === 0) { return true; } foreach ($this->roles as $role) { if ($role === "?") { if ($user->getIsGuest()) { return true; } } elseif ($role === User::ROLE_USER) { if (!$user->getIsGuest()) { return true; } // Check if the user is logged in, and the roles match } elseif (!$user->getIsGuest() && $role === $user->identity->role) { return true; } } return false; } }這里就直接借用Yii2自帶的yiifiltersAccessRule來(lái)控制權(quán)限規(guī)則。但是由于Yii2-User在創(chuàng)建user數(shù)據(jù)表的時(shí)候并沒(méi)有role這個(gè)字段,所以我們需要手動(dòng)添加,你可以直接在mysql敲命令行,或者也可以通過(guò)數(shù)據(jù)庫(kù)管理工具來(lái)添加。
最后更新一下我們的StatusController.php文件,這里的behaviors()方法會(huì)做出一些調(diào)整:
[ "class" => VerbFilter::className(), "actions" => [ "delete" => ["post"], ], ], "access" => [ "class" => AccessControl::className(), // We will override the default rule config with the new AccessRule class "ruleConfig" => [ "class" => AccessRule::className(), ], "only" => ["index","create", "update", "delete"], "rules" => [ [ "actions" => ["index","create"], "allow" => true, // Allow users, moderators and admins to create "roles" => [ User::ROLE_USER, User::ROLE_MODERATOR, User::ROLE_ADMIN ], ], [ "actions" => ["update"], "allow" => true, // Allow moderators and admins to update "roles" => [ User::ROLE_MODERATOR, User::ROLE_ADMIN ], ], [ "actions" => ["delete"], "allow" => true, // Allow admins to delete "roles" => [ User::ROLE_ADMIN ], ], ], ], ]; }我們上面根據(jù)不同等級(jí)的用戶(hù)賦予不同的訪(fǎng)問(wèn)權(quán)限,這時(shí)候,如果你先logout出來(lái),再登錄回去,你還是可以看到這些status,但是一旦你點(diǎn)擊
delete(刪除按鈕),你將會(huì)看到一個(gè)報(bào)錯(cuò)的頁(yè)面:我們手動(dòng)創(chuàng)建的role是成功,但是我們?cè)趺唇o一個(gè)注冊(cè)的用戶(hù)默認(rèn)的權(quán)限呢,我們這里就是想實(shí)現(xiàn)在新用戶(hù)注冊(cè)的時(shí)候賦予用戶(hù)ROLE_USER的角色和權(quán)限。由于Yii2-User是在vendordektriumyii2-usermodelsRegistrationForm.php這個(gè)文件里面進(jìn)行創(chuàng)建新的用戶(hù)的,我門(mén)這里只要修改一個(gè)小地方,找到register()方法:
public function register() { if ($this->validate()) { $user = $this->module->manager->createUser([ "email" => $this->email, "username" => $this->username, "password" => $this->password, "role"=>10, // add this line User::ROLE_USER; ]); return $user->register(); } return false; }添加"role"=>10就可以了。
如果你想證明一下我們的權(quán)限是否正確,你可以手動(dòng)修改數(shù)據(jù)庫(kù)中的role字段的數(shù)值,然后在進(jìn)行修改和刪除等操作,看看是否可以正確運(yùn)行。
權(quán)限控制其實(shí)可以說(shuō)是Yii2的一大特色和亮點(diǎn),在這里可能并沒(méi)有說(shuō)得很清晰,只是簡(jiǎn)單地實(shí)現(xiàn)了一些規(guī)則,有機(jī)會(huì)借助Yii2 Advanced Template來(lái)實(shí)現(xiàn)一下。
源碼會(huì)放在 Github:https://github.com/JellyBool/helloYii
下一節(jié)下一節(jié)嘗試集成一個(gè)編輯器和做一下url的美化,內(nèi)容應(yīng)該會(huì)比較簡(jiǎn)單
Happy Hacking
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/21044.html
摘要:原文來(lái)自這一篇文章的開(kāi)頭就無(wú)需多言了,緊接著上一篇的內(nèi)容和計(jì)劃,這一篇我們來(lái)說(shuō)說(shuō)的和。,那既然這樣,我們就來(lái)實(shí)現(xiàn)一下唄。所以我們首先需要將表中的幾條數(shù)據(jù)刪掉。下一節(jié)再詳細(xì)講講吧,這一節(jié)寫(xiě)下來(lái)貌似要說(shuō)的實(shí)在有點(diǎn)多。 原文來(lái)自:https://jellybool.com/post/programming-with-yii2-behaviors-and-validat... 這一篇...
摘要:開(kāi)始使用郵箱配置好了之后,我們就可以開(kāi)始使用了,首先我們來(lái)修改一下我們的導(dǎo)航欄,因?yàn)槲覀兿雽?shí)現(xiàn)的就是我們常??吹降脑趯?dǎo)航欄的右側(cè)的注冊(cè)和登錄按鈕。 原文來(lái)自: https://jellybool.com/post/programming-with-yii2-integrating-user-regi... 本來(lái)打算昨晚寫(xiě)的這篇教程,但是忙著約會(huì)去了,所以現(xiàn)在補(bǔ)上吧。 上一篇...
摘要:而這些問(wèn)題目前的最好解決方案就是集成一個(gè)編輯器,鑒于大家這里不是指程序員都是喜歡所見(jiàn)即所得,所以,這里我主要是演示怎么集成所見(jiàn)即所得的富文本編輯器。 原文來(lái)自: https://jellybool.com/post/programming-with-yii2-rich-text-input-with-redactor 首先,很慚愧的是,前幾天都出去外面玩了,沒(méi)有及時(shí)更新教程,...
摘要:而且很明顯地,我們可以看到,一旦輸入框在失去焦點(diǎn)的時(shí)候,如果里面沒(méi)有輸入任何內(nèi)容,每個(gè)輸入框就會(huì)有相應(yīng)的錯(cuò)誤提示,用戶(hù)體驗(yàn)很不錯(cuò)。 原文來(lái)自: https://jellybool.com/post/programming-with-yii2-exploring-mvc-forms-a... 上一篇文章我們簡(jiǎn)單地實(shí)現(xiàn)了Yii2框架安裝和Hello World,而在這一篇文章當(dāng)中...
摘要:利用渲染后臺(tái)模板后臺(tái)的模板我們采用利用插播一曲是一個(gè)完全響應(yīng)管理模板。基于框架,易定制模板。適合多種屏幕分辨率,從小型移動(dòng)設(shè)備到大型臺(tái)式機(jī)。內(nèi)置了多個(gè)頁(yè)面,包括儀表盤(pán)郵箱日歷鎖屏登錄及注冊(cè)錯(cuò)誤錯(cuò)誤等頁(yè)面。 作者:白狼 出處:http://www.manks.top/yii2_fra... 本文版權(quán)歸作者,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保...
閱讀 2837·2021-09-02 15:11
閱讀 967·2019-08-26 18:18
閱讀 1934·2019-08-26 11:57
閱讀 3396·2019-08-23 16:59
閱讀 2062·2019-08-23 16:51
閱讀 2371·2019-08-23 16:11
閱讀 3215·2019-08-23 14:58
閱讀 1166·2019-08-23 11:34