2013-03-17 12 views
5

Tôi đang cố gắng triển khai xác thực dựa trên HTTP thông qua số Zend\Authentication\Adapter\Http như được giải thích trong the ZF2 documentation about the HTTP Authentication Adapter.Chặn quyền truy cập qua Xác thực HTTP bằng Zend Framework 2

Tôi muốn chặn mọi yêu cầu đến cho đến khi tác nhân người dùng được xác thực, tuy nhiên tôi không chắc chắn về cách triển khai điều này trong mô-đun của mình.

Làm cách nào để thiết lập ứng dụng Zend \ Mvc của mình để từ chối quyền truy cập vào bộ điều khiển của tôi?

Trả lời

11

Điều bạn đang tìm kiếm có lẽ là người nghe được đính kèm với sự kiện Zend\Mvc\MvcEvent::EVENT_DISPATCH trong đơn đăng ký của bạn.

Theo thứ tự, đây là những gì bạn phải làm để chặn quyền truy cập vào bất kỳ hành động nào thông qua bộ điều hợp xác thực. Trước hết, xác định một nhà máy đó là trách nhiệm sản xuất bộ chuyển đổi xác thực của bạn:

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

nhà máy này về cơ bản sẽ cung cấp cho bạn một adapter auth cấu hình và trừu tượng lôgic instantiation nó đi.

Hãy di chuyển trên và đính kèm một người biết lắng nghe sự kiện dispatch ứng dụng của chúng tôi để chúng tôi có thể chặn bất kỳ yêu cầu với tiêu đề xác thực không hợp lệ:

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

Và sau đó cấu hình module mặc định, mà trong trường hợp này đã được chuyển đến 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', 
     ), 
    ), 
); 

Đây là bản chất của cách bạn có thể hoàn thành công việc.

Rõ ràng, bạn cần phải đặt một cái gì đó giống như một tập tin my_app.auth.local.php trong thư mục config/autoload/ của bạn, với các thiết lập cụ thể đối với môi trường hiện tại của bạn (xin lưu ý rằng tập tin này không nên được cam kết SCM của bạn):

<?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', 
     ), 
    ), 
); 

Cuối cùng, nếu bạn cũng muốn có mã có thể kiểm tra tốt hơn, bạn có thể muốn di chuyển trình lắng nghe được định nghĩa là đóng cửa cho một lớp riêng thực hiện Zend\EventManager\ListenerAggregateInterface.

Bạn có thể đạt được kết quả tương tự bằng cách sử dụng ZfcUser được hỗ trợ bởi Zend\Authentication\Adapter\Http, kết hợp với BjyAuthorize, xử lý logic người nghe đối với các hành động trái phép.

+0

tôi đã nhận lỗi này trong Module.php nộp "Fatal error: Call to Phương pháp xác định Zend \ MVC \ Application :: đính kèm () ". Tôi nghĩ rằng đó là một cái gì đó liên quan đến $ application-> đính kèm. Bạn có bất cứ ý tưởng gì có thể sai? –

+0

Cái xấu của tôi - phải là '$ application-> getEventManager() -> đính kèm (...)' - sửa lỗi – Ocramius

1

trả lời của @ocramius là chấp nhận câu trả lời Nhưng bạn quên để mô tả thế nào để viết hai tập tin basic_password.txtdigest_passwd.txt

Theo Zend 2 Official Doc about Basic Http Authentication:

  • basic_passwd.txt tập tin chứa tên người dùng, lĩnh vực (các lĩnh vực tương tự vào cấu hình của bạn) và mật khẩu thuần túy -><username>:<realm>:<credentials>\n

  • digest_passwd.txt tập tin chứa tên người dùng, lĩnh vực (các lĩnh vực cùng vào cấu hình của bạn) và băm mật khẩu dùng MD5 hash -><username>:<realm>:<credentials hashed>\n

Ví dụ:

nếu basic_passwd.txt file:

user:MyApp Site:password\n 

Sau đó digest_passwd.txt file:

user:MyApp Site:5f4dcc3b5aa765d61d8327deb882cf99\n