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