0

我正在使用 ZendFramework 3 组件开发 REST API。我决定使用中间件验证(验证)每个请求,如果请求有效,则传递给普通控制器操作以检索资源并发送回响应。

  1. 这个概念是否正确?使用中间件包装控制器?

  2. 如何使用以下代码和配置将请求传递给控制器​​?中间件

//file: myapp/module/Auth/src/Middleware/Authorize.php

namespace Auth\Middleware;

use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Json\Json;
use Zend\Http\Response;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\Response\RedirectResponse;

class Authorize
{
    public function __invoke($request, $response)
    {
        // Validate $request code goes here ...

        $response->getBody()->write('Hello World!');
        return $response;
    }
}

路由器配置

//file: myapp/module/Auth/config/module.config.php
namespace Auth;

use Zend\Router\Http\Segment;
use Zend\ServiceManager\Factory\InvokableFactory;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;

return [
    'controllers' => [
        'factories' => [
            Controller\AuthController::class =>Controller\Factory\AuthControllerFactory::class,
        ],

    ],

    'service_manager' => [
        'factories' => [
            \Zend\Authentication\AuthenticationService::class => Service\Factory\AuthenticationServiceFactory::class,
            Service\AuthAdapter::class => Service\Factory\AuthAdapterFactory::class,
            Service\AuthManager::class => Service\Factory\AuthManagerFactory::class,
            Middleware\Authorize::class => InvokableFactory::class,
        ],
    ],

    'router' => [
        'routes' => [
            'auth' => [
                'type'    => Segment::class,
                'options' => [
                    'route' => '/auth[/:action[/:id]]',
                    'constraints' => [
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id'     => '[0-9]+',
                    ],
                    'defaults' => [
                        'controller' => Controller\AuthController::class,
                        'action'     => 'index',
                    ],
                ],
            ],
            'user' => [
                'type'    => Segment::class,
                'options' => [
                    'route' => '/user[/:action[/:id]]',
                    'constraints' => [
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id'     => '[0-9]+',
                    ],
                    'defaults' => [
                        'middleware' => [
                            Middleware\Authorize::class,
                            Controller\UserController::class,
                        ],
                        'controller' => Controller\UserController::class,
                        'action'     => 'index',
                    ],
                ],
            ],
        ],
    ],

    'view_manager' => [
        'template_path_stack' => [
            'auth' => __DIR__ . '/../view',
        ],
    ],

    'doctrine' => [
        'driver' => [
            __NAMESPACE__ . '_driver' => [
                'class' => AnnotationDriver::class,
                'cache' => 'array',
                'paths' => [__DIR__ . '/../src/Entity']
            ],
            'orm_default' => [
                'drivers' => [
                    __NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
                ]
            ]
        ]
    ],
];
4

1 回答 1

0

因此,查看您的代码,让我印象深刻的是以下配置:

'defaults' => [
    'middleware' => [
        Middleware\Authorize::class,
        Controller\UserController::class,
    ],
    'controller' => Controller\UserController::class,
    'action'     => 'index',
],

您只能使用其中一个选项,不能同时使用两者,这是因为在 ZF3 中,中间件是从事件侦听器分派的,因此禁用了传统分派循环的其余部分。

因此,您可以同时删除控制器和操作行。

对于其余部分,这个概念是正确的,您绝对可以通过这种方式添加身份验证。如果您刚刚开始您的项目,我建议您使用 Zend Expressive。对您而言,不同之处在于您可以在任何其他中间件之前应用身份验证操作,而在 ZF3 中,您必须手动将其添加到每个路由。

于 2017-10-22T20:32:57.237 回答