2017-04-14 77 views
1

在一個項目中,我目前的工作,我有嵌套資源這樣Laravel嵌套資源安全

route()->resources('user', 'UserController'); 
route()->resources('user.place', 'PostController'); 
route()->resources('user.place.picture', 'PictureController'); 

一切工作正常,我沿着每次傳遞用戶等的ID ...

訣竅是當你來到一個地方,如果這是你的,我顯示按鈕來編輯和做一些動作。所以我檢查$place.user_id == $user.id是否顯示按鈕。 /user/1/place/2爲Place.show:

打一點,因爲到例如訪問地方煤礦的,我有以下URL後。

我主人這樣的按鈕顯示,我可以修改,但如果另一個用戶(USER_ID 2爲例)使用相同的URL,看我的地方,他不能改變什麼,但可以看到的地方。

我發現那是什麼,如果該用戶使用相同的URL,但改變USER_ID挖掘那麼他就可以完全訪問的地方,對其進行修改。

因此,爲了防止這一點,我添加了另一個條件:Auth::user()->id == $user->id

什麼我不知道是如果有一個解決方案來防止這種行爲,因爲如果我要保護一個嵌套的資源的每個方法它的變長並且難以執行。當我來到更高層次user.place.picture。我想我每次下去都需要增加一層安全性。 $picture->place_id == $place->id等。

所以,當我打印一個鏈接,以便用戶可以點擊它用正確的用戶,地點,照片的身份證再沒有什麼阻止或檢查,如果一個ID已被修改。如果最後一個被修改,那麼就沒有問題,因爲它會檢索另一個元素。但是,如果我們修改父母的身份證,這可能會很危險,特別是當我一路授予某些訪問權限時。

希望有一個簡單的解決方案,我錯過了!

+0

檢出策略(https://laravel.com/docs/5.4/authorization) – Robert

回答

2

首先,我認爲你根本不需要執行這個檢查;

$place.user_id == $user.id

因爲你已經發現,這是從URL得到的$user很容易被操縱,從而是後衛沒有價值。您已經添加了支票以確保當前登錄的UserPlace的所有者,但這應該是您唯一的支票,您不需要兩者。

如果我理解正確的話,這聽起來像一個完美的使用情況下使用Policies in Laravel。該文檔是非常全面的,但我會嘗試和總結一下您的具體使用情況:

  • 生成Policy,例如PlacePolicy
  • 對於你的使用情況,在這種策略中,您將創建一個update()方法,它接受作爲參數,該User(登錄的用戶)和Place(的地方,他們試圖訪問)
  • update()方法上該PlacePolicy現在可以確定,通過任何手段,如果User可以因此更新Place

,它可能是這樣的;

<?php 

namespace App\Policies; 

use App\Place; 
use App\User; 

class PlacePolicy 
{ 
    /** 
    * Determine if the given place can be updated by the User. 
    * 
    * @param \App\User $user 
    * @param \App\Place $place 
    * @return bool 
    */ 
    public function update(User $user, Place $place) 
    { 
     return $place->user_id == $user->id; 
    } 
} 

這是一個非常簡單的檢查 - 但你基本上可以做任何事情絕對這裏來確定給定用戶是否可以對其他模型的動作。

注意:您需要註冊一個的ServiceProvider這項政策,請參閱有關如何做到這一點

有了這個Policy到位上面鏈接的文檔,你可以採取的有用的工具陣列的優勢Laravel提供。例如,你可以利用刀片can指令做這樣的事情:

@can('update', $place) 
    < SHOW THE EDIT BUTTON > 
@endcan 

您還可以通過Middleware申請Policy類,以防止頁面首先被訪問:

Route::get('/user/{user}/place/{place}' .....)->middleware('can:update,place'); 

希望這足以讓你在路上! :)