# 優雅的權限
我們在上一節的開發當中,使用了大量重復的權限檢驗方法,例如 `$user_id = Session::get('user.id');`,
可是每次使用都要進行復制一遍,長期下來代碼將會變成又長又臭的面條,改一發而動全身,這樣的代碼可維護性大大降低,所以我們需要把這些代碼抽離,進行解耦。
## 權限架構
我們前面的章節已經創建過了用戶是否登入的中間件 `application\http\middleware\Auth.php`,所以現在只需要判斷當前操作用戶是否與登入用戶一致就行了。
設計的權限架構如下所示:
策略方法進行一致性對比 -> 將行為注冊至鉤子 -> 控制器驗證輸出
創建文件 `application\behavior\UserPolicy.php`:
~~~php
<?php
namespace app\behavior;
use think\facade\Session;
class UserPolicy
{
public function run($params)
{
return
(int) Session::get('user.id') === (int) $params
? true
: false;
}
}
~~~
這段代碼中,`run` 方法表示默認執行的邏輯操作,可以看到 return 的下一行判斷:如果當前用戶未登入或一致性不符,就會拋出 false。
請注意,在前面章節中所講述過 PHP 的全等判斷標準,事實上是要求“類型,值”一致,如果你這樣寫:
~~~php
Session::get('user.id') === $params
// Session::get('user.id') 類型為 string
// $params 類型為 int
// return false
~~~
所以在做全等(三個等號)判斷時,一定要注意這點。
接下來,我們將在中間件內使用鉤子調用策略,鍵入命令 `php think make:middleware UserAuthorize` 并打開創建好的中間件文件:
`application\http\middleware\UserAuthorize.php`
~~~php
<?php
namespace app\http\middleware;
use think\facade\Hook;
class UserAuthorize
{
public function handle($request, \Closure $next)
{
// 注冊 UserPolicy 策略,傳入請求的 ID 值,再根據上面的代碼進行判斷
$result = Hook::exec('app\\behavior\\UserPolicy', $request->id);
return
$result
? $next($request)
: redirect('user/session/create')->with('validate', '非法操作');
}
}
~~~
接著打開之前創建好的兩個控制器:
`application\user\controller\Auth.php`
`application\user\controller\Session.php`
將里面的中間件名稱 `Auth` 更名為 `UserAuthorize`
~~~php
'Auth' => [
'except' => [
'create',
'save'
]
],
//更改后
'UserAuthorize' => [
'except' => [
'create',
'save'
]
],
~~~
然后刪除之前判斷用戶一致的多余代碼
`application\user\controller\Auth.php`
~~~php
public function edit($id)
{
// 刪除
$user_id = Session::get('user.id');
if ($user_id !== $id) {
return redirect('user/auth/edit', ['id' => $user_id]);
}
public function update(Request $request, $id)
{
// 刪除
$user_id = Session::get('user.id');
if ($user_id !== $id) {
return redirect('user/auth/edit', ['id' => $user_id])->with('validate', '非法操作');
}
~~~
然后在當前頁面下按下 ctrl+f,并在第一行鍵入 $user_id,第二行鍵入 $id,之后點擊如下圖所示的按鈕進行全局替換:
[](https://imgchr.com/i/eEC3Hx)
本小節所寫內容都是為了避免“面條式代碼”,所謂“面條式代碼”就是將一行代碼多處復制使用,在后續維護中如果需要修改某一項功能,則需要找到所有被復制的代碼一一修改,這樣不僅毫無觀賞性,并且會對后續開發造成極大困擾。
- 第一章. 基礎信息
- 1.1 序言
- 1.2 關于作者
- 1.3 本書源碼
- 1.4 反饋糾錯
- 1.5 安全指南
- 1.6 捐助作者
- 第二章. 開發環境布置
- 2.1 編輯器選用
- 2.2 命令行工具
- 2.3 開發環境搭建
- 2.4 瀏覽器選擇
- 2.5 第一個應用
- 2.6 Git 工作流
- 第三章. 構建頁面
- 3.1 章節說明
- 3.2 靜態頁面
- 3.3 Think 命令
- 3.4 小結
- 第四章. 優化頁面
- 4.1 章節說明
- 4.2 樣式美化
- 4.3 局部視圖
- 4.4 路由鏈接
- 4.5 用戶注冊頁面
- 4.6 集中視圖
- 4.7 小結
- 第五章. 用戶模型
- 5.1 章節說明
- 5.2 數據庫遷移
- 5.3 查看數據表
- 5.4 模型文件
- 5.5 小結
- 第六章. 用戶注冊
- 6.1 章節說明
- 6.2 注冊表單
- 6.3 用戶數據驗證
- 6.4 注冊失敗錯誤信息
- 6.5 注冊成功
- 6.6 小結
- 第七章. 會話管理
- 7.1 章節說明
- 7.2 會話
- 7.3 用戶登錄
- 7.4 退出
- 7.5 小結
- 第八章. 用戶 CRUD
- 8.1 章節說明
- 8.2 重構代碼
- 8.3 更新用戶
- 8.4 權限系統
- 8.5 列出所有用戶
- 8.6 刪除用戶
- 8.7 訪客模式
- 8.8 優化前端
- 8.9 小結
- 第九章. 微博 CRUD
- 9.1 章節說明
- 9.2 微博模型
- 9.3 顯示微博
- 9.4 發布微博
- 9.5 微博數據流
- 9.6 刪除微博
- 9.7 小結