Slim 4 中的路由中间件不会停止调用路由中的可调用对象
Route Middleware in Slim 4 doesn't stop invoking the callable in the route
我正在为 Slim4 中的授权中间件而苦恼。这是我的代码:
$app = AppFactory::create();
$app->add(new Authentication());
$app->group('/providers', function(RouteCollectorProxy $group){
$group->get('/', 'Project\Controller\ProviderController:get');
})->add(new SuperuserAuthorization());
身份验证中间件检查用户并正常工作。
ProviderController中的get方法是
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 :/
路由中间件不应该阻止请求进入应用程序并且立即 return 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?
Slim 4 使用 PSR-15 compatible middlewares. There is good example 如何在 PSR-15 元文档中实现授权中间件。如果您不想进一步处理请求,则需要避免调用 $handler->handle($request)
。
如您在示例中所见,如果请求未经授权,则会 returned 响应不同于 $handler->handle($request)
的 return 值。这意味着你的意思是:
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
在某种程度上是正确的,但是你应该通过return在之前调用处理程序,或抛出异常并让错误处理程序处理它。
这是一个简单的中间件,它随机授权一些请求并为其他请求抛出异常:
$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/
路径几次(记住中间件随机操作)
我正在为 Slim4 中的授权中间件而苦恼。这是我的代码:
$app = AppFactory::create();
$app->add(new Authentication());
$app->group('/providers', function(RouteCollectorProxy $group){
$group->get('/', 'Project\Controller\ProviderController:get');
})->add(new SuperuserAuthorization());
身份验证中间件检查用户并正常工作。
ProviderController中的get方法是
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 :/
路由中间件不应该阻止请求进入应用程序并且立即 return 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?
Slim 4 使用 PSR-15 compatible middlewares. There is good example 如何在 PSR-15 元文档中实现授权中间件。如果您不想进一步处理请求,则需要避免调用 $handler->handle($request)
。
如您在示例中所见,如果请求未经授权,则会 returned 响应不同于 $handler->handle($request)
的 return 值。这意味着你的意思是:
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
在某种程度上是正确的,但是你应该通过return在之前调用处理程序,或抛出异常并让错误处理程序处理它。
这是一个简单的中间件,它随机授权一些请求并为其他请求抛出异常:
$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/
路径几次(记住中间件随机操作)