Route Middleware in Slim 4 doesn't stop invoking the callable in the route

守給你的承諾、 提交于 2020-04-30 06:31:26

问题


I'm strugling with authorization middleware in Slim4. Here's my code:

$app = AppFactory::create();
$app->add(new Authentication());

$app->group('/providers', function(RouteCollectorProxy $group){
    $group->get('/', 'Project\Controller\ProviderController:get');
})->add(new SuperuserAuthorization());

Authentication middleware checks the user and works fine.

The method get in ProviderController is

public function get(Request $request, Response $response): Response{
    $payload = [];
    foreach(Provider::all() as $provider){
        $payload[] = [
            'id' => $provider->id,
            'name' => $provider->name,
        ];
    }
    $response->getBody()->write(json_encode($payload));
    return $response;
}

The SuperuserAuthorization looks like this

class SuperuserAuthorization{
    public function __invoke(Request $request, RequestHandler $handler): Response{
        $response = $handler->handle($request);
        $authorization = explode(" ", $request->getHeader('Authorization')[0]);
        $user = User::getUserByApiKey($authorization[1]);
        if(! Role::isSuperuser($user)){
            return $response->withStatus(403);//Forbidden
        }
        return $response;
    }
}

The thing is that even though the user is not a superuser, the application continues executing. As a result I get json with all the providers and http code 403 :/

Shouldn't route middleware stop the request from getting into the app and just return 403 right away?

I know that I can create new empty response with status 403, so the data won't come out, but the point is that the request should never get beyond this middleware, am I right or did I just misunderstand something here…

Any help will be appreciated :)

------------- SOLUTION ----------------

Thanks to @Nima I solved it. The updated version of middleware is:

class SuperuserAuthorization{
    public function __invoke(Request $request, RequestHandler $handler): Response{
        $authorization = explode(" ", $request->getHeader('Authorization')[0]);
        $user = User::getUserByApiKey($authorization[1]);
        if(! Role::isSuperuser($user)){
            $response = new Response();
            return $response->withStatus(403);//Forbidden
        }
        return $handler->handle($request);
    }
}

回答1:


Shouldn't route middleware stop the request from getting into the app and just return 403 right away?

Slim 4 uses PSR-15 compatible middlewares. There is good example of how to implement an authorization middleware in PSR-15 meta document. You need to avoid calling $handler->handle($request) if you don't want the request to be processed any further.

As you can see in the example, if the request is not authorized, a response different from the return value of $handler->handle($request) is returned. This means your point saying:

I know that I can create new empty response with status 403, so the data won't come out, but the point is that the request should never get beyond this middleware

is somehow correct, but you should prevent the request from going further by returning appropriate response before invoking the handler, or throwing an exception and let the error handler handle it.

Here is a simple middleware that randomly authorizes some of requests and throws an exception for others:

$app->group('/protected', function($group){
    $group->get('/', function($request, $response){
        $response->getBody()->write('Some protected response...');
        return $response;
    });
})->add(function($request, $handler){
    // randomly authorize/reject requests
    if(rand() % 2) {
        // Instead of throwing an exception, you can return an appropriate response
        throw new \Slim\Exception\HttpForbiddenException($request);
    }
    $response = $handler->handle($request);
    $response->getBody()->write('(this request was authorized by the middleware)');
    return $response;
});

To see different responses, please visit /protected/ path a few times (remember the middleware acts randomly)



来源:https://stackoverflow.com/questions/60176905/slim-4-middleware-redirect-on-the-way-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!