我正在尝试通过 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/