今天遇到了一個小問題但是為了解決用了很久的時間,覺得有必要記錄一下這個過程。
首先是設置了一個用于身份驗證中間件Admin,代碼如下:
public function handle($request, Closure $next) {
if(session('user')->user_group != 1){
$msg ="對不起,您無權訪問訪問本頁面!";
return view('error',compact('msg'));
}
return $next($request);
}
如果使用管理員身份登錄則一切正常,但是如果使用非管理員身份登錄則會出現一個錯誤。
搜索了很久終于在Laracasts發現有人有人針對這個錯誤提問,其中一個回答是
There are two types of middleware one that are applied to the global level and one that we apply to the route level. The route level middleware run inside the router's own local middleware stack. When we return some view from controller i.ereturn view('auth/login') the router's method dispatchToRoute explicitly prepares the Response object so that it can be used inside the global middleware (or in general can be returned to the browser). That said, only returning a view never prepares the response so the route lever middlewares throw such errors. you can fix it by simply returning a response rather then a rendered view.
由于英語水平不行并沒有完全看懂,個人理解是Laravel有兩種級別的中間件,一種是應用于全局級別的中間件一種是應用于路由級別的中間件,在只返回一個視圖時不會準備響應,所以頭信息為空,導致setCookie()
無法調用。要修復這個問題應該返回一個Response
對象,使用該類的view()
方法來取代直接返回一個渲染視圖。
//replace your `view returns` with `reponse returns` e.g:
return view('home.index')
//replace with
return response()->view('home.index')
而另一個回答則建議更好的處理方式是自己在中間件里準備響應
use Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
..
public function handle($request, Closure $next) {
$response = $this->prepareResponse($request, $next($request));
if ($this->isReading($request) || $this->tokensMatch($request)) {
return $this->addCookieToResponse($request, $response);
}
throw new TokenMismatchException;
}
// this one is in fact a copy-paste from the Router
protected function prepareResponse($request, $response) {
if ( ! $response instanceof SymfonyResponse) {
$response = new Response($response);
}
return $response->prepare($request);
}
[原文鏈接][1] 以后有時間再深入研究
[1]:https://laracasts.com/discuss/channels/general-discussion/disable-global-verifycsrftoken-and-use-as-middleware-doesnt-work-setcookie-on-null