Zend框架身份验证和重定向

时间:2009-03-17 16:05:28

标签: zend-framework routing

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

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

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

我是否需要链接到preDispatch或Front Controller插件的Action Controller?我如何进行重定向并仍保留基本URL等内容?

3 个答案:

答案 0 :(得分:4)

答案 1 :(得分:1)

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

答案 2 :(得分:1)

在我正在进行的项目中,我遇到了各种用户遇到浏览器超时的问题。这意味着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插件加载控制器类属性并检查它的值。虽然,我发现在数据库中维护访问策略比在整个代码库中传播它们更容易......: - )