在Zend中,有没有更好的方法来检查用户是否具有Identity()?

时间:2011-12-01 06:44:36

标签: zend-framework

目前,我正在使用Zend_Auth::getInstance()->hasIdentity()检查我的用户是否在每个需要登录的控制器中登录。我觉得我在练Zend可怕,所以我想问更有经验的人,知道这是否是正确的方法呢?如果没有,你能告诉我它是什么吗?

3 个答案:

答案 0 :(得分:1)

我们使用Controller plugin(在application.ini配置文件中引导)来处理我们的身份验证。它在preDispatch()阶段检查请求的控制器/操作,并与ACL对象匹配(可以从DB,配置文件,XML等中获取)。如果用户没有访问目标控制器/操作的权限,则会在会话中存储一条消息,并将用户重定向到另一个页面,显示访问禁止消息。

如果用户需要具有访问目标控制器/操作的身份验证,则会通过修改请求对象将用户重定向到登录操作。

使用此插件无需在每个控制器中检查用户身份验证/ ACL,因此所有“访问”代码都将包含在一个文件中,即“访问插件”。

为了检查用户身份,我们大多使用“Zend_Auth :: getInstance() - > hasIdenity()”的相同方法,但这只是显示用户是否经过身份验证。 Zend_Auth的'''getIdentity()'''方法返回当前用户身份,但同样只返回身份而不是更多。但是,如果您需要更多用户信息,可以将用户信息存储在会话中。

我们将用户实现为数据模型,因此每个用户都被定义为一个对象。在用户通过登录操作进行身份验证后,我们会创建相应的用户对象并将其存储在用户会话中,如下所示:

// This could be a sample code in AuthController/processloginAction()
// suppose $username is validated before and stores the username
$user = new Default_Model_User($username);
// now $user is our user object, suppose $log is a Zend_Log instance
$log->info("user id '{$user->getId()}' username: '{$user->getUsername()}' logged in");
$sess = Zend_Session_Namespace('auth');
$sess->user = $user;

从现在开始,'auth'会话命名空间的$ user属性是用户对象,包含您需要的所有信息,而不仅仅是身份。每当你想检查用户是否登录时(除了使用Zend_Auth),你可以在用户会话上检查这个值的可用性:

$sess = Zend_Session_Namespace('auth');
if (!isset($sess->user) || !$sess->user) {
    // user is not logged in, redirect to login page
}
$user = $sess->user;
/*@var $user Default_Model_User*/
$email = $user->getEmail();

现在我们检查了身份验证,并且可以访问用户信息(电子邮件,电话等)。

答案 1 :(得分:1)

我在http://www.hermanradtke.com/blog/more-reliable-authentication-in-zend-framework/的博客中使用了与Herman Radtke描述的方法类似的方法。基本上创建一个控制器插件,如farzad所述:

class My_Authentication extends Zend_Controller_Plugin_Abstract
{

    private $_whitelist;

    public function __construct()
    {
        $this->_whitelist = array(
            'index/login'
        );
    }

    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $controller = strtolower($request->getControllerName());
        $action = strtolower($request->getActionName());
        $route = $controller . '/' . $action;

        if (in_array($route, $this->_whitelist)) {
            return;
        }

        $auth = Zend_Auth::getInstance();
        if ($auth->hasIdentity()) {
            return;
        }

        self::setDispatched(false);
        // handle unauthorized request...
    }
}

然后在你的bootstrap中注册该插件:

public function run() {
  $front->registerPlugin(new My_Authentication());
}

我通常采用这种方法,并将Zend_Acl集成到系统中。为此,我将在下面定义插件:

class My_Acl_Authentication扩展Zend_Controller_Plugin_Abstract     {

    private $_acl;

    public function __construct($acl)
    {
        $this->_acl = $acl
    }

    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $controller = strtolower($request->getControllerName());
        $action = strtolower($request->getActionName());
        $route = $controller . '/' . $action;

        if (in_array($route, $this->_whitelist)) {
            return;
        }

        $auth = Zend_Auth::getInstance();
        $role = 'anonymous';
        if ($auth->hasIdentity()) {
            $role = $auth->getStorage->read()->role;
        }

        if ($this->_acl->isAllowed($role, $route)) {
            return;
        }

        self::setDispatched(false);
        // handle unauthorized request...
    }
}

如果你走这条路,还有一些工作要做,特别是你必须设置ACL,然后你还必须将用户的角色存储在auth存储中。

答案 2 :(得分:0)

完全可以这样做但是为了避免重复该代码,您可以从作为Zend_Controller_Action的子类的类A扩展所有控制器。然后在这个类中声明一个方法

    protected function hasIdentity()
    {
      return Zend_Auth::getInstance()->hasIdentity();
    }

现在在您的控制器中,它是A的子类,您只需执行$this->hasIdentity();而不是