今天遇到了一个小问题但是为了解决用了很久的时间,觉得有必要记录一下这个过程。
首先是设置了一个用于身份验证中间件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