我如何全局保护我的所有控制器(我的登录控制器除外)以确保我的应用程序在所有点都是安全的(没有隐藏的后门到ajax调用等)。我以为我可能会把它放在我的bootstrap文件中,但这感觉不对?我试图避免向每个控制器添加任何代码。
建议?
答案 0 :(得分:11)
编辑:这是@singles响应的补充。
你必须明白有两件事。 验证和验证。 Auth告诉您谁是用户,并且您可以例如将没有Auth的用户重定向到登录控制器,并在登录后设置auth身份。然后,Acl系统根据Auth数据做出是/否决定(可以是用户ID,也可以是角色,存储在Auth存储中。
好的解决方案是拥有2个控制器插件(在bootstrap上按照正确的顺序注册,然后是Auth,然后是Acl)。如果您不使用Controller插件,则必须在每个控制器中调用Acl检查。如果你总是需要它,那就使用插件。
如果您没有从Zend_Auth返回身份,请在 Auth插件中实施preDispatch()
以设置匿名身份。
这是一个真实的代码片段:
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$module = $request->getModuleName();
$controller = $request->getControllerName();
$action = $request->getActionName();
$auth = Zend_Auth::getInstance();
if (!$auth->hasIdentity()) {
// set a default anonymous identity
$auth->getStorage()->write(array('name' => 'anonymous','role' => 1,));
}
(...)
对于 Acl控制器插件,任务也在preDispatch()
中。您可以为每个请求的URL启动acl检查(因此对于每个用户请求,甚至是ajax)。这是一个部分片段,所以这只是一个如何处理事情的例子:
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$controller = $request->controller;
$module = $request->module;
$action = $request->action;
// here you should code something nice retrieving you Zend_Acl object
// with some caching options maybe, building roles, ressources, etc
$this->_acl = $this->getAcl();
if (!$this->_acl->isCurrentUserAllowed($module,'see')) {
$auth = Zend_Auth::getInstance();
$identity = $auth->hasIdentity('identity')? $auth->getIdentity() : null;
if(isset($identity)) {
if($identity['name'] == 'anonymous') {
// WARNING: avoid infinite redirect loops on login page
if (!($request->getControllerName() == 'login'
&& $request->getActionName()=='login'
&& $request->getModuleName() == 'default')) {
$request->setControllerName('login')
->setActionName('login')
->setModuleName('default');
return;
(...)
在这个系统中,最后一个重要的部分是LoginController,如果成功登录,你应该启动身份记录:
(...)
$auth = Zend_Auth::getInstance();
Zend_Session::regenerateId();
$storage = $auth->getStorage();
$rowobject = $authAdapter->getResultRowObject(null,'passwd');
$storage->write((array)$rowobject);
(...)
答案 1 :(得分:4)
你应该为此编写ACL插件并在前端控制器中注册它。如果您实现插件等功能,您可以灵活地在下一个应用程序中使用它 - 无需从自定义控制器扩展每个控制器。
资源:
1. Front Controller Plugins in Zend Framework - 插件如何在ZF中工作
2. Zend_Acl / Zend_Auth example scenario - ACL插件的许多可能实现之一
3. Google - 还有很多其他资源
答案 2 :(得分:0)
嗯,你需要有一个系统的入口点:)
这可以通过扩展Zend_Controller_Action来实现,比如说:
abstract class MyController extends Zend_Controller_Action {
public function preDispatch(){
// do the logic
}
}
现在每个控制器只需要扩展MyController,你就是安全的。
答案 3 :(得分:0)
我在一个实现中的方式是在我的应用程序路径中创建一个名为Auth.php的文件。然后我打开了我想要保护的每个控制器并添加了行
include_once APPLICATION_PATH . '/Auth.php';
在调用parent :: init()之前的init()方法。
至于Auth.php文件本身,它基本上使用Zend_Auth进行身份验证。成功后,我会保存用户的身份,以便以后在应用程序中使用
$this->view->assign('myIdentity', Zend_Auth::getInstance()->getIdentity());
如果失败,我会重定向到登录页面并传递一些参数,以便登录页面知道我登录后将发送给我的位置。
这不是一个优雅的解决方案,但它可靠且相对快速且易于实施。