http://localhost:8080/test/jobs
http://locahost:8081/api/jobs
OAuth api 라우트 설정 중에 뜬 에러.
// routes\api.php
Route::get('/test', function (Request $request) {
return $request->user();
})->middleware('auth:api');
원래는 validation에 실패하면 세션에서 $errors에 에러메시지를 담아서 넘겨주고 그 내용이 출력되어야 하는데, $errors 변수 자체가 정의되지 않았다는 에러를 뱉었다.
라라벨 버전이 올라가면서 middleware가 동작하는 방식이 바뀌었다고 한다.
// Laravel 5.1 - app/Http/Kernel.php
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
];
위의 코드는 라라벨 5.1버전 app/Http/Kernel.php
의 기본 설정값이다. 이 배열은 글로벌 HTTP middleware stack이다. 무슨 말이나면, 모든 request에서 저 클래스들이 동작한다는 거다.
그 중에 눈여겨 볼 것이 밑에서 두번째 \Illuminate\View\Middleware\ShareErrorsFromSession::class
이다. 이걸 까보면 아래와 같은 동작을 하는 것을 확인할 수 있다.
public function handle($request, Closure $next)
{
$this->view->share(
'errors', $request->session()->get('errors') ?: new ViewErrorBag
);
return $next($request);
}
즉, 이 놈이 모든 뷰에서 $errors 변수를 만들어서 사용할 수 있게 해주는거다.
그런데 이게 버전업이 되면서 위치가 바뀌었다. 이제 global middleware는 메인터넌스만 체크하고, web
이라는 middleware group이 생기면서 global middleware에 있던 대부분의 것들이 이곳으로 옮겨졌다.
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
],
];
두가지 방법으로 의외로 간단하게 해결이 가능하다. Undefined variable: errors
에러만 해결되고 $request->user()
에 대한 값이 null
이어서 정작 제일 중요한 $request->user()->jobs
를 불러오려고 하면 Trying to get property 'jobs' of non-object
에러가 뜬다.
api 라우트를 설정해주는 api.php
에서 middleware group을 지정해주면 해결된다.
Route::group(['middleware' => ['api']], function () {
Route:: get('/test', function(Request $request) {
return $request->user()->jobs;
});
});
\Illuminate\View\Middleware\ShareErrorsFromSession::class
를 $middleware
에 포함시켜준다. (이게 좋은 방법인지는 모르겠는데 어쨌든 문제는 해결된다.)
\Illuminate\Session\Middleware\StartSession::class
도 포함해준다. 안그러면 Session store not set on request.
에러가 뜬다. 순서는 StartSession
을 1번보다 먼저 써준다.
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
];
protected $middlewareGroups = [
(생략)
// \Illuminate\View\Middleware\ShareErrorsFromSession::class,
];
선임한테도 도움을 구하고 다시 시도해봤는데 해결법을 혼자 찾지 못해서 결국 팀장님께 도움을 받았다.
먼저, 미들웨어를 제대로 타고 있는지 확인해보았다.
에러가 발생되는 현재 auth 서버의 api.php
를 보면 'auth:api' 미들웨어를 타도록 설정해주었다.
Route::middleware('auth:api')->get('/jobs', function (Request $request) {
return $request->user()->jobs;
});
이게 실제로 어디로 타고 넘어가는지 보기 위해 Kernel.php
를 보면, \App\Http\Middleware\Authenticate
로 넘어가는 걸 알 수 있다.
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
Authenticate.php
를 까서handle()
에서 잘 처리되고 있는지 확인하기 위해 break point를 찍고 xdebug로 디버깅을 해보았다.
실제로 handle()에서는 잘 걸리는 것을 확인했지만, 로그인 인증이 제대로 되지 않고 분기에 걸려서 response()->view()
로 넘어가고 있었다.
회사에서 사용하는 프로젝트는 5.x에서 올라온 것이라 8.x의 기본설정값과 비교해보기 위해 새 프로젝트를 임의로 만들어주었다.
비교해보니 handle()
의 인자값부터 달랐다. 기본설정에서는 세번째 인자로 ...$guards
를 받고 있었다. 일단 handle()
로 넘어오면 authenticate()
에서 다시 $guards
를 확인해서 다음 단계로 넘어가고 있다.
회사 프로젝트를 처음 만들때는 api일때를 고려하지 않았기 때문에 api 주소일때 authenticate()
로 넘어가는 분기 조건을 추가해주고 거기에서 $guards
를 체크하도록 수정해주었다.
public function handle($request, Closure $next, ...$guards)
{
if ($request->is('api/*')) {
$this->authenticate($request, $guards);
} else {
...
}
return $next($request);
}
protected function authenticate($request, array $guards)
{
if (empty($guards)) {
$guards = [null];
}
foreach ($guards as $guard) {
if ($this->auth->guard($guard)->check()) {
return $this->auth->shouldUse($guard);
}
}
throw new AuthenticationException('Unauthenticated.', $guards);
}
이제 다시 client에서 결과를 보여줄 페이지를 새로고침해보면...
json으로 결과를 예쁘게 출력해준다!
xdebug로 디버깅, bash 열어서 로그 확인 등 자유롭게 할 수 있도록 공부할 것.
https://stackoverflow.com/questions/34420590/laravel-5-2-validation-errors?rq=1
검색어
laravel route auth:api
laravel middleware api detect