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

标签 php routes middleware slim-4

我正在为 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;
    }
}

问题是即使用户不是 super 用户,应用程序也会继续执行。结果,我得到了所有提供者的 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);
    }
}

最佳答案

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



超薄4用PSR-15兼容的中间件。有好的example如何在 PSR-15 元文档中实现授权中间件。您需要避免调用 $handler->handle($request)如果您不希望进一步处理该请求。

在示例中可以看到,如果请求未授权,则返回值与 $handler->handle($request) 不同的响应被退回。这意味着您的意思是:

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



在某种程度上是正确的,但是您应该通过在调用处理程序之前返回适当的响应来防止请求进一步进行,或者抛出异常并让错误处理程序处理它。

这是一个简单的中间件,它随机授权一些请求并为其他请求抛出异常:
$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/几次路径(记住中间件随机 Action )

关于php - Slim 4 中的路由中间件不会停止调用路由中的可调用对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59731468/

相关文章:

php - mySql 中半正矢公式的正确数据类型是什么

php - 使用 require_once 后 undefined variable

javascript - 使用 Bootstrap 模式作为成人内容警告的问题

ruby-on-rails - Rails、关联、路由、 Controller 、kerfuffle

javascript - io.sockets.on 无法在 Node.js 中的路由内工作

php - 什么是 CMIString4096 以及如何提取其中的数据?

php - 在 Laravel 8 中找不到 404

ruby - 当 Content-Type 为 application/json 时自动使用 JSON 编码 Rack 输出

javascript - 让 Redux DevTools 工作

ruby - 结合 Rack::Builder 和 Rack::Cascade