使用Zend_Auth保护所有控制器

Ben*_*owe 6 php security zend-framework

我如何全局保护我的所有控制器(我的登录控制器除外)以确保我的应用程序在所有点都是安全的(没有隐藏的后门到ajax调用等).我以为我可能把它放在我的bootstrap文件中,但这感觉不对?我试图避免向每个控制器添加任何代码.

建议?

reg*_*ero 11

编辑:这是@singles响应的补充.

你必须明白有两件事.AuthAcl.Auth告诉您谁是用户,并且您可以例如将没有Auth的用户重定向到登录控制器,并在登录后设置auth身份.然后,Acl系统根据Auth数据做出是/否决定(可以是用户ID,也可以是角色,存储在Auth存储中).

好的解决方案是拥有2个控制器插件(在引导程序上以良好的顺序注册,然后是Auth,然后是Acl).如果您不使用Controller插件,则必须在每个控制器中调用Acl检查.如果你总是需要它,那么使用插件.

落实preDispatch()在你验证插件,例如,如果你有一个从Zend_Auth的没有身份重返设置一个匿名的身份.这是真实的代码片段:

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,));
    }
(...)
Run Code Online (Sandbox Code Playgroud)

对于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;
(...)
Run Code Online (Sandbox Code Playgroud)

在这个系统中,最后一个重要的部分是LoginController,如果成功登录,你应该启动身份记录:

(...)
$auth = Zend_Auth::getInstance();
Zend_Session::regenerateId();
$storage = $auth->getStorage();
$rowobject = $authAdapter->getResultRowObject(null,'passwd');
$storage->write((array)$rowobject);
(...)
Run Code Online (Sandbox Code Playgroud)