2016-11-29 63 views
1

我試圖找到一種乾淨的方式來覆蓋AuthorizationException,以便在策略失敗時接收一個可以傳回的動態字符串。Laravel 5.3當策略失敗時傳遞AuthorizationException異常

事情我知道我可以做的是:

1)包住政策與一個try-catch控制器,然後再次拋出一個自定義異常,需要一個特定的字符串,這似乎有點冗長

2)abort(403, '...')在政策之前返回,這似乎是因爲政策有點哈克已經做的工作​​

,然後在/例外/處理器::使我可以發送迴響應JSON

有一個更好的方式來做到這一點,以獲得在政策失敗的答覆中的消息?或者是1或2我的最佳選擇。

+0

因此,如果引發AuthorizationException,您希望生成自定義錯誤? – atefth

+0

嗨@atefth yah有點像驗證失敗時,你得到的錯誤包,但在這種情況下,你會得到一個失敗的政策包與消息,將根據失敗的政策作爲JSON響應而有所不同。 – mtpultz

回答

1

我注意到如果您在使用Laravel例外的策略中使用throw AuthorizationException($message),它會跳出策略,但會繼續在控制器中執行,並且不會繼續執行到Handler::render。我認爲這是他們以某種方式處理異常,但我無法找到他們在做什麼......所以如果有人發現這種情況,我仍然想知道。

如果你創建自己的AuthorizationException扔它,它就會如預期停止執行,並放到Handler::render所以我最終加入這個方法我的政策:

use App\Exceptions\AuthorizationException; 

// ... removed for brevity 

private function throwExceptionIfNotPermitted(bool $hasPermission = false, bool $allowExceptions = false, $exceptionMessage = null): bool 
{ 
    // Only throw when a message is provided, or use the default 
    // behaviour provided by policies 
    if (!$hasPermission && $allowExceptions && !is_null($exceptionMessage)) { 

     throw new \App\Exceptions\AuthorizationException($exceptionMessage); 
    } 

    return $hasPermission; 
} 

新的異常,在政策投擲只在\App\Exceptions

namespace App\Exceptions; 

use Exception; 

/** 
* The AuthorizationException class is used by policies where authorization has 
* failed, and a message is required to indicate the type of failure. 
* --- 
* NOTE: For consistency and clarity with the framework the exception was named 
* for the similarly named exception provided by Laravel that does not stop 
* execution when thrown in a policy due to internal handling of the 
* exception. 
*/ 
class AuthorizationException extends Exception 
{ 
    private $statusCode = 403; 

    public function __construct($message = null, \Exception $previous = null, $code = 0) 
    { 
     parent::__construct($message, $code, $previous); 
    } 

    public function getStatusCode() 
    { 
     return $this->statusCode; 
    } 
} 

處理異常,並提供在Handler::render()以JSON響應消息:

public function render($request, Exception $exception) 
{ 
    if ($exception instanceof AuthorizationException && $request->expectsJson()) { 

     return response()->json([ 
      'message' => $exception->getMessage() 
     ], $exception->getStatusCode()); 
    } 

    return parent::render($request, $exception); 
} 

我也將其從登錄Handler::report中刪除。

-1

Laravel確實有一個選項來傳遞參數來定製在通過Gate類的實施GateContract訪問的Controller類的authorize()方法由Gate門面提供錯誤

然而,他們似乎忘了這些參數傳遞給負責返回錯誤消息allow()/deny()方法,在HandlesAuthorization特質實現。


您需要通過以下步驟來傳遞這些參數:

  1. 修改authorize方法在vendor/laravel/framework/src/Illuminate/Auth/Access/Gate.php文件

    public function authorize($ability, $arguments = []) { 
        $result = $this->raw($ability, $arguments); 
        if ($result instanceof Response) { 
         return $result; 
        } 
    
        return $result ? $this->allow() : $this->deny($arguments); 
    } 
    
  2. 呼叫authorize從一個額外的參數控制,即:自定義$message -

    $message = "You can not delete this comment!"; 
    $response = $this->authorize('delete', $message); 
    

我已經做了pull request來解決這個問題,希望有人很快就會合並。

+0

不錯,我們使用的模型策略'$ user-> can(...);'所以我會尋找這種相同類型的解決方案,看看它是否工作。此外,看起來像你的公關已暫時/永久擱置:( – mtpultz