在我的 ZF2 应用程序中,我添加了以下事件侦听器,但是我想让操作的执行实际停止,但这不会发生。
public function setEventManager(EventManagerInterface $events)
{
parent::setEventManager($events);
$controller = $this;
$events->attach('dispatch', function ($e) use ($controller) {
$request = $e->getRequest();
$method = $request->getMethod();
$headers = $request->getHeaders();
// If we get here, based on some conditions, the original intended action must return a new JsonViewModel()...
return new JsonViewModel([]); // However, this doesn't do anything.
}, 100); // execute before executing action logic
}
Run Code Online (Sandbox Code Playgroud)
根据您的评论,我假设您正在进行某种身份验证。您可以完美地使用事件管理器。但是,我不会将侦听器绑定到单个控制器。如果您的 API 增加,您可能希望将 API 拆分到多个控制器上,并且您的身份验证会遇到麻烦。
我的解决方案是创建一个监听器来监听 Zend\Mvc\Application 的调度事件。这是在控制器本身的事件之前触发的事件。
use Zend\Mvc\MvcEvent;
public function onBootstrap(MvcEvent $e)
{
$app = $e->getApplication();
$em = $app->getEventManager();
$sm = $app->getServiceManager()->getSharedManager();
$listener = new Listener\Authentication();
$identifier = 'MyModule\Controller\ApiController';
$em->attach($identifier, MvcEvent::EVENT_DISPATCH, $listener, 1000);
}
Run Code Online (Sandbox Code Playgroud)
这样,侦听器将附加到所有以 标识的控制器上MyModule\Controller\ApiController。监听器将在这些控制器的每次调度调用上被触发。如果您需要,您的侦听器可以使整个调度循环短路:
use Zend\Http\Request as HttpRequest;
use Zend\Mvc\MvcEvent;
use Zend\Json\Json;
use Zend\View\Model\JsonModel;
class Authentication
{
public function __invoke(MvcEvent $e)
{
$request = $e->getRequest();
if (!$request instanceof HttpRequest) {
// Don't run on CLI requests
return;
}
if ($result->isValid()) {
// Say you get auth result and all is OK
return;
}
// Case 1: short-circuit and return response, this is the fast way
// The response I use here is the HTTP problem API
$message = array(
'httpStatus' => 401,
'title' => 'Unauthorized',
'detail' => 'You are unauthorized to perform this request',
);
$response = $e->getResponse();
$response->setStatusCode(401);
$response->getHeaders()->addHeaderLine('Content-Type', 'application/json');
$response->setContent(Json::encode($message);
return $response;
// Case 2: don't short circuit and stop propagation, you're using the JSON renderer
$e->getResponse()->setStatusCode(401);
$message = array(
'httpStatus' => 401,
'title' => 'Unauthorized',
'detail' => 'You are unauthorized to perform this request',
);
$model = new JsonModel($message);
return $model;
}
}
Run Code Online (Sandbox Code Playgroud)
我建议您使用第一种方法(自己返回响应),因为您将缩短完整的调度过程并跳过请求的完整完成。如果您真的依赖视图和响应发送者,请使用第二种情况。
现在,如果您需要通过此系统进行身份验证的控制器,请将标识符添加到此控制器:
namespace MyModule\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class MyFooBarApiController extends AbstractActionController
{
protected $eventIdentifer = 'MyModule\Controller\ApiController';
// your code here
}
Run Code Online (Sandbox Code Playgroud)
如果您需要在未经验证的情况下允许某些请求(我总是使用白名单!),您可以在您的侦听器中执行此操作:
use Zend\Mvc\Route\RouteMatch;
$routematch = $e->getRouteMatch();
if (!$routematch instance of RouteMatch) {
// It's a 404, don't perform auth
return;
}
$route = $routematch->getMatchedRouteName();
if (
($request->isPost() && 'foo/bar' === $route)
|| ($request->isGet() && 'baz/bat' === $route)
) {
// We allow these requests to pass on without auth
return;
}
Run Code Online (Sandbox Code Playgroud)
在您的代码中,您可以明确检查请求方法和路由名称。如果需要路由参数,可以使用$routematch->getParam('id').
| 归档时间: |
|
| 查看次数: |
1059 次 |
| 最近记录: |