2016-01-26 55 views
12

我正在開發一個laravel應用程序,我意識到可以用Policy完成的任務完全可以通過Middleware完成。假設我想阻止用戶更新路線,如果他/她不是信息的所有者,我可以從路線中輕鬆檢查,並且可以從策略中執行相同的操作。Laravel:路由中間件和策略之間的區別

所以我的問題是,爲什麼我應該使用policy在中間件,反之亦然

+2

另一種方法,我認爲你應該嘗試一下這樣的:*中間件*用於*認證*而*政策*是使用*授權*。 – haakym

回答

10

路線中間件,可以應用請求處理,以大範圍的路由,而不是重複在每個控制器動作的代碼 - 檢查認證重定向客人就是一個很好的例子。相反,控制器包含特定路線/動作所特有的邏輯 - 您可以使用中間件來實現這一點,但是您需要爲每條路線的邏輯單獨使用中間件,並且它們都會變得非常混亂。

策略/能力只是一種檢查用戶權限的方式 - 您可以從控制器,中間件或其他任何地方查詢它們。它們只返回真或假,因此它們不等同於控制器或中間件。大多數時間能力都會將用戶與另一個模型進行比較,該模型將根據發送給控制器操作的標識符加載,但也可能有一些與中間件一起使用的應用程序。

25

我目前正在通過一個小的重構與我的角色,權限和路線,並問自己同樣的問題。

在表面層面看來,真正的中間件和策略執行的是相同的總體思路。檢查用戶是否可以做他們正在做的事情。

僅供參考這裏的laravel文檔...

中間件 「我可以看看嗎?我可以去嗎?」

HTTP中間件提供了一種便捷的機制來過濾HTTP 請求進入您的應用程序。例如,Laravel包含一個 中間件,該中間件驗證您的應用程序的用戶是否已認證 。如果用戶未通過身份驗證,則中間件將 將用戶重定向到登錄屏幕。但是,如果用戶是 已通過身份驗證,則中間件將允許該請求進一步進入應用程序 。

當然,除了驗證之外,還可以編寫額外的中間件來執行各種任務 。一個CORS中間件可能是 負責將正確的標題添加到所有響應中,然後從您的應用程序中刪除 。日誌記錄中間件可能會將所有傳入請求 記錄到您的應用程序中。

https://laravel.com/docs/master/middleware#introduction

在我的閱讀,中間件是關於請求級別的操作。在「這個用戶看到一個頁面?」或「這個用戶可以在這裏做些什麼嗎?」的條款?

如果是這樣,它將轉到與該頁面關聯的控制器方法。有趣的是,中間件可能會說:「是的,你可能會去那裏,但我會寫下你要去的地方。」等等。

一旦完成。它沒有更多的控制權或者說用戶在做什麼。另一種方式我認爲它是中間人。

政策 「我可以這樣做嗎?我可以改變嗎?」

除了提供認證服務,開箱, Laravel還提供了一種簡單的方式來組織授權邏輯和資源 控制訪問。有多種方法和 幫助程序可以幫助您組織您的授權邏輯,我們將在本文檔中介紹其中的每個方法。

https://laravel.com/docs/master/authorization#introduction

策略然而,似乎更關注。用戶是否可以更新任何條目,或只有他們的?

這些問題似乎適用於對資源上的所有操作調用進行組織的控制器方法。檢索此對象,存儲或更新文章。

由於tjbb mentioned,中間件可以使路線非常混亂,難以管理。這是一個例子,從我的路線文件:

問題

Route::group(['middleware' =>'role:person_type,person_type2',], function() { 
     Route::get('download-thing/{thing}', [ 
      'as' => 'download-thing', 
      'uses' => '[email protected]' 
     ]); 
    }); 

這會非常艱難,我的路線文件閱讀!

與政策

//ThingController 
public function download(Thing $thing) 
{ 
    //Policy method and controller method match, no need to name it 
    $this->authorize($thing); 

    //download logic here.... 
} 
+0

'as'=>'download-thing'是做什麼的?我覺得它可以像'在處理這個請求的其餘部分時充當這個模型'一樣。我試圖找到它的文件,但迄今沒有運氣。 編輯:我找到了。它可以讓你「命名」一條路線,以便在生成URL或重定向用戶時使用。對我來說遠不是那麼有用:( – daraul

+0

很好的答案!這項政策的另一個好處是你可以用'can'命令在刀片模板中使用它。 – Adam