【问题标题】:Zend Framework Authentication and RedirectionZend 框架身份验证和重定向
【发布时间】:2009-03-17 16:05:28
【问题描述】:

Zend 框架中提供限制区域并将用户重定向到登录页面的最佳方法是什么?我想要做的是在我的控制器上为受限页面设置一个标志:

class AdminController extends Zend_Controller_Action
{
    protected $_isRestricted = true;
    ....

并让插件检查控制器是否受到限制以及用户是否已通过身份验证,否则将它们重定向到登录页面。如果我直接在控制器的 preDispatch 中执行此操作,我可以使用 $this->_redirect(),但查看 Action Helpers,他们将无法访问它。在每个需要它的控制器中复制/粘贴身份验证检查代码也是很多重复代码。

我需要链接到 preDispatch 的 Action Controller 还是 Front Controller 插件?我将如何进行重定向并仍然保留基本 URL 之类的内容?

【问题讨论】:

    标签: zend-framework routing


    【解决方案1】:

    【讨论】:

      【解决方案2】:

      对于一个项目,我扩展了 Zend_Controller_Action,并在该类的 preDispatch 中检查了是否已登录。我可以在每个操作的基础上使用 init() 来覆盖它,该 init() 检查操作名并关闭需求(或 preDispatch() 调用它的父级进行实际检查)。

      【讨论】:

        【解决方案3】:

        在我正在进行的一个项目中,我遇到了各种用户遇到浏览器超时的问题。这意味着 Zend_Auth 不再存在于注册表中,用户无法访问所需的页面/功能。

        为了阻止这种情况发生,我设置了一个插件(如您所建议的那样)并让该插件在 preDispatch() 中执行检查。下面是一个例子:

        class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
        {
            public function run()
            {
                $front  = Zend_Controller_Front::getInstance();
                $front->registerPlugin(new App_Controller_Plugin_Timeout());
                parent::run();
            }
        }
        

        超时类实现任何 Zend_Auth 或 Zend_Acl 要求,通过下面的函数使用检查。

        class App_Controller_Plugin_Timeout extends Zend_Controller_Plugin_Abstract
        {
            /**
             * Validate that the user session has not timed out.
             * @param Zend_Controller_Request_Abstract $request
             * @return void
             * @todo Validate the user has access to the requested page using Zend_Acl
             */
            public function preDispatch(Zend_Controller_Request_Abstract $request)
            {
                $frontController = Zend_Controller_Front::getInstance();
                $controllerName  = $frontController->getRequest()->getControllerName();
                $actionName      = $frontController->getRequest()->getActionName();
                $authInstance    = Zend_Auth::getInstance();
        
                /** If the controller is not the Auth or Error controller, then check for
                 *  a valid authorized user and redirect to the login page if none found */
                if (($controllerName !== 'auth') && ($controllerName !== 'index') && ($controllerName !== 'error')) {
                    if (!$authInstance->hasIdentity()) {
                        $this->_response->setRedirect('/index/timeout')->sendResponse();
                        exit;
                    }
                } else if (($controllerName == 'index') || (($controllerName == 'auth') && ($actionName !== 'logout'))) {
                    /** If running the Auth or Index (default) controller (and not the logout
                     *  action), check if user already signed in and redirect to the welcome page */
                    if ($authInstance->hasIdentity()) {
                        $this->_response->setRedirect('/general/welcome')->sendResponse();
                        exit;
                    }
                }
            }
        }
        

        ....

        /**
         * Test that the input user belongs to a role based on the user input and
         * the values loaded into the Acl registry object setup when the site first
         * loads
         *
         * @param   mixed|Zend_Auth $userData
         * @param   string          $userRole
         * @return  boolean
         * @throws  Zend_Exception  When invalid input is provided
         */
        
        public function isUserMemberOfRole($userData, $userRole)
        {
            if (empty($userData)) {
                $auth = Zend_Auth::getInstance();
                if($auth->hasIdentity()) {
                    $userData = $auth->getIdentity();
                } else {
                    return FALSE;
                }
            }
        
            if (!is_string($userRole)){
                throw new Zend_Exception('Invalid input provided to ' . __METHOD__);
            }
        
            // Setup the required variables and access the registry for the Acl values
            $rolesTable = new App_Model_Internal_UsersToRoles();
            $registry   = Zend_Registry::getInstance();
            $acl        = $registry->get('acl');
            $roles      = $rolesTable->getUserRoles($userData); // returns an array of values
        
            foreach ($roles as $value) {
                if ($value['Name'] == $userRole) {
                    return $acl->isAllowed($value['Name'], null, $userRole);
                }
            }
        }
        

        我在数据库表中实现了用户访问,然后在 Bootstrap->run() 中初始化为“_init”函数,如下所示:

        protected function _initAclObjectForUserRoles()
        {
            $userTable = new App_Model_Internal_Roles();
            $acl       = new Zend_Acl();
        
            $userRoles = $userTable->fetchAll();
            $roles     = $userRoles->toArray();
        
            // Cycle through each Role and set the allow status for each
            foreach($roles as $value) {
                $department = $value['Name'];
                $acl->addRole(new Zend_Acl_Role($department));
                $acl->allow($department, null, $department);
            }
        
            // Add the new Acl to the registry
            $registry = Zend_Registry::getInstance();
            $registry->set('acl', $acl);
        }
        

        因此,使用这种方法,您可以通过从数据库加载的角色将访问限制设置到 Zend_Acl 对象中,或者您可以通过 Timeout 插件加载控制器类属性并检查它的值。虽然,我发现在数据库中维护访问策略比在整个代码库中传播它们更容易...... :-)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-07
          • 1970-01-01
          • 2021-11-27
          相关资源
          最近更新 更多