authentication - 使用 Zend Framework 2 通过 HTTP 身份验证阻止访问

标签 authentication zend-framework2

我正在尝试通过 Zend\Authentication\Adapter\Http 实现基于 HTTP 的身份验证。如 the ZF2 documentation about the HTTP Authentication Adapter 中所述.

我想阻止每个传入的请求,直到用户代理通过身份验证,但是我不确定如何在我的模块中实现它。

如何设置我的 Zend\Mvc 应用程序以拒绝访问我的 Controller ?

最佳答案

您正在寻找的可能是连接到 Zend\Mvc\MvcEvent::EVENT_DISPATCH 的监听器。您的应用程序的事件。

为了阻止通过身份验证适配器访问任何操作,您必须执行以下操作。首先,定义一个负责生产您的身份验证适配器的工厂:

namespace MyApp\ServiceFactory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Authentication\Adapter\Http as HttpAdapter;
use Zend\Authentication\Adapter\Http\FileResolver;

class AuthenticationAdapterFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $config         = $serviceLocator->get('Config');
        $authConfig     = $config['my_app']['auth_adapter'];
        $authAdapter    = new HttpAdapter($authConfig['config']);
        $basicResolver  = new FileResolver();
        $digestResolver = new FileResolver();

        $basicResolver->setFile($authConfig['basic_passwd_file']);
        $digestResolver->setFile($authConfig['digest_passwd_file']);
        $adapter->setBasicResolver($basicResolver);
        $adapter->setDigestResolver($digestResolver);

        return $adapter;
    }
}

这个工厂基本上会给你一个配置的身份验证适配器,并将其实例化逻辑抽象掉。

让我们继续并在我们的应用程序的 dispatch 上附加一个监听器。事件,以便我们可以阻止任何具有无效身份验证 header 的请求:

namespace MyApp;

use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\ModuleManager\Feature\BootstrapListenerInterface;
use Zend\EventManager\EventInterface;
use Zend\Mvc\MvcEvent;
use Zend\Http\Request as HttpRequest;
use Zend\Http\Response as HttpResponse;

class MyModule implements ConfigProviderInterface, BootstrapListenerInterface
{
    public function getConfig()
    {
        // moved out for readability on SO, since config is pretty short anyway
        return require __DIR__ . '/config/module.config.php';
    }

    public function onBootstrap(EventInterface $event)
    {
        /* @var $application \Zend\Mvc\ApplicationInterface */
        $application    = $event->getTarget();
        $serviceManager = $application->getServiceManager();

        // delaying instantiation of everything to the latest possible moment
        $application
            ->getEventManager()
            ->attach(function (MvcEvent $event) use ($serviceManager) {
            $request  = $event->getRequest();
            $response = $event->getResponse();

            if ( ! (
                $request instanceof HttpRequest
                && $response instanceof HttpResponse
            )) {
                return; // we're not in HTTP context - CLI application?
            }

            /* @var $authAdapter \Zend\Authentication\Adapter\Http */
            $authAdapter = $serviceManager->get('MyApp\AuthenticationAdapter');

            $authAdapter->setRequest($request);
            $authAdapter->setResponse($response);

            $result = $adapter->authenticate();

            if ($result->isValid()) {
                return; // everything OK
            }

            $response->setBody('Access denied');
            $response->setStatusCode(HttpResponse::STATUS_CODE_401);

            $event->setResult($response); // short-circuit to application end

            return false; // stop event propagation
        }, MvcEvent::EVENT_DISPATCH);
    }
}

然后是模块默认配置,在本例中被移动到 MyModule/config/module.config.php :

return array(
    'my_app' => array(
        'auth_adapter' => array(
            'config' => array(
                'accept_schemes' => 'basic digest',
                'realm'          => 'MyApp Site',
                'digest_domains' => '/my_app /my_site',
                'nonce_timeout'  => 3600,
            ),
            'basic_passwd_file'  => __DIR__ . '/dummy/basic.txt',
            'digest_passwd_file' => __DIR__ . '/dummy/digest.txt',
        ),
    ),
    'service_manager' => array(
        'factories' => array(
            'MyApp\AuthenticationAdapter'
                => 'MyApp\ServiceFactory\AuthenticationAdapterFactory',
        ),
    ),
);

这是你如何完成它的本质。

显然,您需要放置类似 my_app.auth.local.php 的内容。文件在您的config/autoload/目录,具有特定于您当前环境的设置(请注意,此文件不应提交给您的 SCM):

<?php
return array(
    'my_app' => array(
        'auth_adapter' => array(
            'basic_passwd_file'  => __DIR__ . '/real/basic_passwd.txt',
            'digest_passwd_file' => __DIR__ . '/real/digest_passwd.txt',
        ),
    ),
);

最后,如果您还想拥有更好的可测试代码,您可能希望将定义为闭包的监听器移动到实现 Zend\EventManager\ListenerAggregateInterface 的自己的类中。 .

您可以使用 ZfcUser 获得相同的结果由 Zend\Authentication\Adapter\Http 支持, 结合 BjyAuthorize ,它处理未授权操作的监听器逻辑。

关于authentication - 使用 Zend Framework 2 通过 HTTP 身份验证阻止访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15467138/

相关文章:

ruby - Rack::Auth::Basic 销毁 session (注销)

c# - 不使用内置成员资格功能时使用 FormsAuthentication.SignOut 是否有意义

authentication - Paw - 支持 https 相互(客户端证书)身份验证?

module - Zend框架2 : Router "resolves to invalid controller class or alias:"

mysql - 在 mysql JOIN 查询的 'ON' 子句中使用 mysql 函数

jquery - 使用 jquery ajax 部署身份验证

reactjs - Cognito/Flask/React:如何登录到后端?

php - 在 Doctrine 2 中加入查询实体

php - 在 "put"方法中获取 zend 框架中的 post 参数

php - 从多对多表中获取对应值和非对应值