Slim 4中的路由中间件不会停止调用路由中的可调用对象 - php

我正在使用Slim4中的授权中间件。这是我的代码:

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

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

身份验证中间件检查用户并正常工作。

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

参考方案

路由中间件是否不应该阻止请求进入应用程序并立即返回403?

Slim 4使用PSR-15兼容的中间件。关于如何在PSR-15元文档中实现授权中间件的很好的example。如果您不希望进一步处理请求,则需要避免调用$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/路径(记住中间件是随机运行的)

PHP:对数组排序 - php

请如何排序以下数组Array ( 'ben' => 1.0, 'ken' => 2.0, 'sam' => 1.5 ) 至Array ( 'ken' => 2.0, 'sam' => 1.5, 'ben' =&…

php:将分钟取整到最近的四分之一小时,然后执行更多操作 - php

最初的问题是这样的:取分钟数->转换为四分之一小时-> 1个四分之一小时为1个单位->输出单位我今天整天都在整理页面,几分钟前我的大脑就停止工作了,我只是不知道如何输出单位数量。我知道在此网站上发布问题会有所帮助。因此,用户输入的分钟数(不是小时和分钟,而是数分钟),站点需要输出单位数量。单位是一个刻钟。分钟总是四舍五入到最近的四分之一小时…

php Singleton类实例将在多个会话中保留吗? - php

举一个简单的例子,如果我想计算一个不使用磁盘存储的脚本的命中次数,我可以使用静态类成员来执行此操作吗?用户1:<?php $test = Example::singleton(); $test->visits++; ?> 用户2:<?php $test = Example::singleton(); $test->visits+…

PHP PDO组按列名称查询结果 - php

以下PDO查询返回以下结果:$db = new PDO('....'); $sth = $db->prepare('SELECT ...'); 结果如下: name curso ABC stack CDE stack FGH stack IJK stack LMN overflow OPQ overflow RS…

PHP strtotime困境 - php

有人可以解释为什么这在我的服务器上输出为true吗?date_default_timezone_set('Europe/Bucharest'); var_dump( strtotime('29.03.2015 03:00', time()) === strtotime('29.03.2015 04:00�…