正當我覺得核心問題都處理的差不多,終於可以來補完其它還沒動工的功能時,突然發現使用者如果手動變更路由中的id,那麼,使用者是可輕易的訪問其它使用者的後台的,不小心做成像facebook那樣,登入的使用者可以互相訪問!
這當然不是應該發生的,原因和先前的問題一樣,在過濾路由時,我們目前是有過濾了登入身份及角色,但沒有確認使用者的後台頁面訪問權限,所以造成只要登入成功,角色是 user
的使用者都可以任意的訪問所有會員的後台,不過這個問題好解決,我們從原本的 Middleware
中下手,增加判斷條件就可以了:
app\Http\Middleware\RedirectByAuthcatedRole.php
if(Auth::user()->role!==$guard){
.....略
}
//通過角色檢查後,接著檢查使用者的id是否和路由的id一樣,管理者排除不檢查
if(Auth::user()->role==='user' && is_numeric($request->route('user_id'))){
return redirect()->route('userhome',Auth::user()->name);
}
return $next($request);
但我接著想到使用者端的後台網址如果都是id的話難免會想去try 就像你在facebook的網址後打上 https://facebook.com/4
會出現祖伯克,雖然網址隨即變成 zuck ,但很多人就會想試試看5,6,7,8是誰?有沒有一種可能,我們對使用者後台的所有路由都做類似的事,但我可以加上身份的檢查,不讓使用者可以去看其他使用者的後台??
其實可以,而且還滿簡單的,我們在 Middleware 中做完角色的檢查後,接著檢查路由參數中的 user_id
是否為數字,如果是數字,就重新導向,並取出 Auth::user()->name
把名字帶入到原本路由中,這樣就會把使用者看到的網址由 id
轉成名字,而原本帶入到 Controller
中的參數也由 $user-id
改成了 $user_name
:
app\Http\Middleware\RedirectByAuthcatedRole.php
.....略
if(is_numeric($request->route('user_id'))){
return redirect()->route('userhome',Auth::user()->name);
};
// 因為會重導向到帶名字的路由所以原本檢查id的方法改成檢查路由中的名稱,一樣排除管理者不檢查
if(Auth::user()->role==='user' && Auth::user()->name!==$request->route('user_id')){
return redirect()->route('userhome',Auth::user()->name);
}
return $next($request);
Controller 不需要太多修改,也不用重新去撈 User
的 id
,直接使用 Auth
來取得 id
就可以了
app\Http\Controllers\UserController.php
function userCenter($user_name){
return Inertia::render('UserHome/UserHome',
//直接使用登入者的Auth資料來取得id
['tests'=>$this->test->testsByUserId(Auth::user()->id)]);
}
以上就是今天的內容了,雖然是有點短,但其實滿實用的,尤其是 Middleware
的用途常常是許多 Laravel
新手會迷惑的地方。