Промежуточное программное обеспечение Route в Slim 4 не останавливает вызов вызываемого в маршруте - PullRequest
4 голосов
/ 14 января 2020

Я борюсь с промежуточным ПО авторизации в Slim4. Вот мой код:

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

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

Промежуточное ПО аутентификации проверяет пользователя и работает нормально.

Метод get в ProviderController равен

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;
}

. SuperuserAuthorization выглядит следующим образом

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;
    }
}

Дело в том, что, хотя пользователь не является суперпользователем, приложение продолжает выполняться. В результате я получаю json со всеми провайдерами и http-кодом 403: /

Не должно ли промежуточное программное обеспечение маршрутизации остановить запрос на вход в приложение и просто сразу вернуть 403?

Я знаю, что могу создать новый пустой ответ со статусом 403, чтобы данные не появлялись, но дело в том, что запрос никогда не должен выходить за рамки этого промежуточного программного обеспечения, я прав или я просто что-то здесь неправильно понял ...

Любая помощь будет оценена по достоинству:)

------------- РЕШЕНИЕ ----------------

Благодаря @Nima я решил это. Обновленная версия промежуточного программного обеспечения:

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 Ответ

3 голосов
/ 14 января 2020

Разве маршрутизация промежуточного программного обеспечения не должна останавливать поступление запроса в приложение и сразу же возвращать 403?

Slim 4 использует PSR-15 совместимое промежуточное ПО. Есть хороший пример того, как реализовать промежуточное ПО авторизации в мета-документе PSR-15. Вам следует избегать вызова $handler->handle($request), если вы не хотите, чтобы запрос обрабатывался дальше.

Как видно из примера, если запрос не авторизован, ответ отличается от возвращаемого значения. $handler->handle($request) возвращается. Это означает, что ваша точка зрения гласит:

Я знаю, что могу создать новый пустой ответ со статусом 403, чтобы данные не появлялись, но суть в том, что запрос никогда не должен выходить за пределы этого промежуточного программного обеспечения.

как-то правильно, но вы должны помешать продвижению запроса дальше, возвращая соответствующий ответ до вызова обработчика или выбрасывая исключение и позволяя обработчик ошибок обрабатывает его.

Вот простое промежуточное ПО, которое случайным образом авторизует некоторые запросы и создает исключение для других:

$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;
});

Чтобы увидеть другие ответы, посетите /protected/ path a несколько раз (помните, что промежуточное ПО действует случайным образом)

...