Search code examples
phplaravel-4stack-traceabort

Suppressing stack trace dump in Laravel log after App::abort(403)


I'm setting up a custom Acl for a Laravel 4.1 application.

My Routes.php file applies a before filter:

// Global authenticator
Route::filter('auth.vle', function()
{
    return (new vleAuth)->authenticate();
});
// Authenticate all requests, except those to /login, /logout and /forgottenpassword
Route::whenRegex('/^(?!login|logout)(.*)$/', 'auth.vle');

and my vleAuth authenticate() method:

public function authenticate()
{
    $this->acl = new vleAclService();
    $endpoint = Route::current()->getAction()['controller'];
    if (!$this->acl->validateEndpoint($endpoint)) {
        Log::info('Routing', array( Route::current()->getUri(), $endpoint));
        App::abort(403, 'Unauthorized action.');
    }
}

When I access an endpoint which I am privileged to access, no problems; and when I access an endpoint that I'm not privileged to access, then I get a Forbidden - We're really sorry but you don't have the necessary permissions to access this page. message, so the authentication is working correctly as far as the "front-end" is concerned, and the routing information in the log bears this out.

However, whenever I try to access an endpoint that I'm not authenticated for, I also get a stack trace dumped in the Laravel log

[2014-06-12 15:00:16] production.INFO: ROUTE VALIDATION ["View_Reviews_ReviewsController@getIndex",false] []
[2014-06-12 15:00:16] production.ERROR: exception 'Symfony\Component\HttpKernel\Exception\HttpException' with message 'Unauthorized action.' in /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:875
Stack trace:
#0 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(211): Illuminate\Foundation\Application->abort(403, 'Unauthorized ac...')
#1 /srv/api/laravel/app/controllers/vleAuth.php(104): Illuminate\Support\Facades\Facade::__callStatic('abort', Array)
#2 /srv/api/laravel/app/controllers/vleAuth.php(104): Illuminate\Support\Facades\App::abort(403, 'Unauthorized ac...')
#3 /srv/api/laravel/app/routes.php(20): vleAuth->authenticate()
#4 [internal function]: {closure}(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#5 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(199): call_user_func_array(Object(Closure), Array)
#6 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(154): Illuminate\Events\Dispatcher->fire('router.filter: ...', Array, true)
#7 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Routing/Router.php(1399): Illuminate\Events\Dispatcher->until('router.filter: ...', Array)
#8 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Routing/Router.php(1262): Illuminate\Routing\Router->callRouteFilter('auth.vle', Array, Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#9 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Routing/Router.php(1246): Illuminate\Routing\Router->callPatternFilters(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#10 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Routing/Router.php(996): Illuminate\Routing\Router->callRouteBefore(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#11 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Routing/Router.php(968): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#12 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(738): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#13 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(708): Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))
#14 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Http/FrameGuard.php(38): Illuminate\Foundation\Application->handle(Object(Illuminate\Http\Request), 1, true)
#15 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Session/Middleware.php(72): Illuminate\Http\FrameGuard->handle(Object(Illuminate\Http\Request), 1, true)
#16 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Cookie/Queue.php(47): Illuminate\Session\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#17 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Cookie/Guard.php(51): Illuminate\Cookie\Queue->handle(Object(Illuminate\Http\Request), 1, true)
#18 /home/vagrant/vleAppV2/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Illuminate\Cookie\Guard->handle(Object(Illuminate\Http\Request), 1, true)
#19 /home/vagrant/vleAppV2/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(606): Stack\StackedHttpKernel->handle(Object(Illuminate\Http\Request))
#20 /home/vagrant/vleAppV2/public/index.php(49): Illuminate\Foundation\Application->run()
#21 {main} [] []

I'm trying to suppress this because I don't want the logs filling up with stack traces; just the log info that I'm recording myself is all I actually need in the logs.

I've tried suppressing it by registering a new error handling function in app/global.php:

App::error(function(Exception $exception, $code)
{
    // Don't log 403s
    if ($exception instanceof Symfony\Component\HttpKernel\Exception\HttpException) {
        return;
    }

    Log::error($exception);
});

but this doesn't seem to have any effect at all.

I've also tried wrapping the App:abort() in vleAuth.authenticate() within a try/catch block, but the Exception appears to have already been handled before this catch, so it hasn't helped either.

I've rerun composer dump-autoload to rebuild all appropriate autoloading, and have restarted the server just in case old scripts are being help in OpCache.

Can anybody tell me how I should be suppressing this stack trace?


Solution

  • The solution was in returning a response from the custom error handling function rather than a null return

    App::error(function(Exception $exception, $code)
    {
        // Don't log 403s
        if ($exception instanceof Symfony\Component\HttpKernel\Exception\HttpException) {
            return Response::view('errors.403', array(), 403);
        }
    
        Log::error($exception);
    });
    

    This still displays the 403 page correctly, but overrides calling the default error handler that was generating the stack trace