2013-03-17 5 views
5

Próbuję zaimplementować uwierzytelnianie oparte na protokole HTTP poprzez Zend\Authentication\Adapter\Http, jak wyjaśniono w the ZF2 documentation about the HTTP Authentication Adapter.Blokowanie dostępu za pośrednictwem uwierzytelniania HTTP za pomocą Zend Framework 2

Chcę zablokować każde przychodzące żądanie do czasu uwierzytelnienia klienta użytkownika, jednak nie jestem pewien, jak zaimplementować to w moim module.

Jak skonfigurować swoją aplikację Zend \ Mvc, aby odmówić dostępu do kontrolerów?

Odpowiedz

11

To, czego szukasz, to prawdopodobnie słuchacz dołączony do zdarzenia Zend\Mvc\MvcEvent::EVENT_DISPATCH Twojej aplikacji.

Oto, co musisz zrobić, aby zablokować dostęp do dowolnej akcji za pośrednictwem adaptera uwierzytelniania. Przede wszystkim należy zdefiniować fabryki, który jest odpowiedzialny za produkcję adaptera uwierzytelniania:

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; 
    } 
} 

Ta fabryka będzie w zasadzie daje skonfigurowany adapter auth i abstrakcyjnej logiki jego instancji oddalony. ruch

Przejdźmy dalej i dołączyć słuchacza dispatch przypadku naszej aplikacji tak, że możemy zablokować każdy wniosek o nieprawidłowych nagłówków uwierzytelniania:

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); 
    } 
} 

a następnie domyślną konfigurację modułu, który w tym przypadku został przeniesiony do 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', 
     ), 
    ), 
); 

To jest esencja tego, jak możesz to zrobić.

Oczywiście, trzeba umieścić coś takiego pliku my_app.auth.local.php w katalogu config/autoload/, z ustawienia specyficzne dla bieżącego środowiska (proszę pamiętać, że ten plik powinien być niezaangażowane do 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', 
     ), 
    ), 
); 

Ostatecznie, jeśli chcesz mieć również lepszy testowalny kod, możesz chcieć przenieść słuchacza zdefiniowanego jako zamknięcie do własnej klasy implementującej Zend\EventManager\ListenerAggregateInterface.

Możesz osiągnąć te same wyniki, używając ZfcUser wspieranego przez Zend\Authentication\Adapter\Http, w połączeniu z BjyAuthorize, który obsługuje logikę słuchacza w przypadku nieautoryzowanych działań.

+0

mam ten błąd w Module.php pliku „Fatal error: Call to metoda niezdefiniowany Zend \ MVC \ Application :: attach () ". Myślę, że jest to coś związanego z $ application-> attach. Czy masz pojęcie, co może być nie tak? –

+0

My bad - powinno być '$ application-> getEventManager() -> attach (...)' - fixing – Ocramius

1

Odpowiedź @ocramius jest zaakceptować odpowiedź Ale zapomnieć opisać Jak napisać dwa pliki basic_password.txt i digest_passwd.txt

według Zend 2 Official Doc about Basic Http Authentication:

  • basic_passwd.txt plik zawiera nazwę użytkownika, sfera (ta sama sfera do konfiguracji) i zwykłe hasło -><username>:<realm>:<credentials>\n

  • digest_passwd.txt plik zawiera nazwę użytkownika, sferę (taka sama realm do konfiguracji) i hasło hashowania Używanie skrótu MD5 -><username>:<realm>:<credentials hashed>\n

Przykład:

jeśli basic_passwd.txt file:

user:MyApp Site:password\n 

Następnie digest_passwd.txt file:

user:MyApp Site:5f4dcc3b5aa765d61d8327deb882cf99\n