【问题标题】:Zend Framework 2 - Global check for authentication with ZFCUserZend Framework 2 - 使用 ZFCUser 进行身份验证的全局检查
【发布时间】:2013-01-03 11:17:50
【问题描述】:

我成功安装了ZFCUser。现在我想知道是否有办法全局检查身份验证。

正如in the wiki 所述,有几种方法可以检查身份验证。它们都有效,但我是否必须在 每一个 操作中都添加 check-if 子句?我所有的网站都应该只有在登录后才能访问,如果没有,您应该重新路由到登录页面。

有人知道是否有一个中心位置我可以放置这个逻辑吗?

【问题讨论】:

    标签: php authentication zend-framework2 zfcuser


    【解决方案1】:

    老实说,我认为为未经身份验证的用户屏蔽每个页面并不是一个好主意。您将如何访问登录页面?

    也就是说,您必须知道正在访问的页面,才能将匿名访问者可以访问的页面列入白名单。首先,我建议包含登录页面。您可以使用他们的路线最简单地检查页面。因此,根据白名单检查当前匹配的路由。如果被阻止,请采取行动。否则,什么都不做。

    一个例子是在一个模块的 Module.php 中,例如你的应用程序:

    namespace Application;
    
    use Zend\Mvc\MvcEvent;
    use Zend\Mvc\Router\RouteMatch;
    
    class Module
    {
        protected $whitelist = array('zfcuser/login');
    
        public function onBootstrap($e)
        {
            $app = $e->getApplication();
            $em  = $app->getEventManager();
            $sm  = $app->getServiceManager();
    
            $list = $this->whitelist;
            $auth = $sm->get('zfcuser_auth_service');
    
            $em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($list, $auth) {
                $match = $e->getRouteMatch();
    
                // No route match, this is a 404
                if (!$match instanceof RouteMatch) {
                    return;
                }
    
                // Route is whitelisted
                $name = $match->getMatchedRouteName();
                if (in_array($name, $list)) {
                    return;
                }
    
                // User is authenticated
                if ($auth->hasIdentity()) {
                    return;
                }
    
                // Redirect to the user login page, as an example
                $router   = $e->getRouter();
                $url      = $router->assemble(array(), array(
                    'name' => 'zfcuser/login'
                ));
    
                $response = $e->getResponse();
                $response->getHeaders()->addHeaderLine('Location', $url);
                $response->setStatusCode(302);
    
                return $response;
            }, -100);
        }
    }
    

    【讨论】:

    • 嗯,不确定...我是凭脑子写的,所以尝试启用 php 错误并将错误级别设置为 -1(意思是所有错误),看看这里出了什么问题。也许找不到路由器,但据我所知,路由器位于路由事件内部回调的onBootstrap 中的$e 内部。如果没有,请尝试从onBoostrap() 方法中的$e 获取路由器,然后像$list$auth 一样导入它。
    • 您需要将new Response 更改为$e->getResponse() 才能完美运行!
    • 感谢您解决这个问题。我相应地更新了我的答案以供将来参考:)
    • 对此我有两个问题。只需要将该代码放在所有模块的一个module.php中吗?在我的情况下,我正在从登录页面对服务器进行 ajax 调用以进行身份​​验证,我必须将路由“MyAction/procces”添加到白名单中;为什么?即使使用我的自定义身份验证服务(没有 ZFCUser),代码似乎也能很好地工作
    • 如果您有新问题,请点击本网站右上角的“提问”按钮。此外:是的,这段代码在每次调用时都会运行,您不需要将它放在每个模块类中。如果您需要更细粒度的用户/ACL 机制,请查看 ZfcUser 和 BjyAuthorize。以上代码仅用于非常简单的设置和说明目的。
    【解决方案2】:

    在 ZF 2.4.2 上,我在 Module.php 中执行此操作

    class module {
    
    protected $whitelist = array(
        'Application\Controller\Login'
    );
    
    public function onBootstrap(MvcEvent $e)
    {
    
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
    
        // add event
        $eventManager->attach('dispatch', array($this, 'checkLogin')); 
    
    }
    
    public function checkLogin($e)
    {
    
        $auth   = $e->getApplication()->getServiceManager()->get("Zend\Authentication\AuthenticationService");
        $target = $e->getTarget();
        $match  = $e->getRouteMatch();
    
        $controller = $match->getParam('controller');
    
        if( !in_array($controller, $this->whitelist)){
            if( !$auth->hasIdentity() ){
                return $target->redirect()->toUrl('/login');
            }
        }
    
    }
    
    //other methods....
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用 ZF2 模块 BjyAuthorize 来阻止/允许基于用户角色(例如 guestuser 等使用 controller guardroute guard 等)访问页面

      【讨论】:

        【解决方案4】:

        人,

        提示,不要忘记在正确的 RouteMatch 语句中添加“使用”:

        use Zend\Mvc\Router\Http\RouteMatch;
        

        这里需要这个:

        if (!$match instanceof RouteMatch)...
        

        如果你忘记了,上面的if有变数

        【讨论】:

          【解决方案5】:

          另一种选择可能是创建自己的抽象控制器超类并实现 onDispatch() 方法,如下所示:

          public function onDispatch(MvcEvent $e) 
          {
              // check authentication here
          
              return parent::onDispatch($e);
          }
          

          您也可以在那里实施白名单:)。

          【讨论】:

          • 我可能错了,但我认为你的意思是叫onDispatch;
          猜你喜欢
          • 1970-01-01
          • 2023-03-18
          • 2014-01-04
          • 1970-01-01
          • 1970-01-01
          • 2020-09-14
          • 1970-01-01
          • 1970-01-01
          • 2014-09-21
          相关资源
          最近更新 更多