验证失败后Zend _forward不起作用(Zend Framework 1)

时间:2013-10-07 11:02:56

标签: php zend-framework

用户授权失败后,我想将它们转发回登录页面。目前,_forward方法导致Zend挂起并发出超时错误(超过30秒)。

登录页面的代码处理登录和注册表单,并转发到授权控制器:

public function indexAction() {

    if ($this->_request->isPost()) {
        $formData = $this->_request->getPost();

        if (array_key_exists('signUp', $formData)) {
            $authAction = 'signup';
            $form = 'signupForm';
        } elseif (array_key_exists('logIn', $formData)) {
            $authAction = 'login';
            $form = 'loginForm';
        }

        if ($this->$form->isValid($formData)) {
            $this->_forward($authAction, 'user-auth', null, $formData);
        } else {
            $this->$form->populate($formData);
        }
    }
}

这很好用,并成功重定向到auth控制器。 auth控制器的登录操作中的代码如下:

public function loginAction() {
    $formData = $this->_request->getPost();

    $authAdapter = new My_Auth_Adapter();
    $authAdapter->setTableName('user')
                ->setIdentity($formData['username'])
                ->setCredential($formData['password'])
                ->setIdentityColumn('username')
                ->setCredentialColumn('password');
    $result = $authAdapter->authenticate();

    if ($result->isValid()) {
        // success, all good
    } else {
        $this->_forward('index', 'login', 'default', $formData);
    } 
}

我们到达这里很好,成功的授权按预期工作。但是在我的else语句中将另一个转发回到原始登录控制器(我希望填充用户名以及回发错误消息)导致程序挂起,尽管重定向工作正常。

我认为这可能是因为登录控制器正在重新检测发布数据而我陷入无限循环,但是将$ formData作为转发的最后一个参数删除并不会改变任何内容。

我还尝试了$ formData ['errMsg'] ='无论'在转发之上,然后检查密钥是否存在或者是否在登录控制器中设置了,但这也没有改变。< / p>

有趣的是,我收到的超时错误引用了Auth DbTable Adapter:

Fatal error: Maximum execution time of 30 seconds exceeded in /Applications/MAMP/MampServer/mysite/library/Zend/Auth/Adapter/DbTable.php on line 174

关于可能发生的事情的任何想法?

2 个答案:

答案 0 :(得分:1)

我认为您在loginAction()indexAction()之间无限循环。

查看对forward()redirect()动作帮助的调用之间的区别。前者forward()将在内部更改$request->isDispatched() == false - 这意味着前端控制器将执行目标控制器操作而无需新的HTTP请求。

结果是$this->_request->isPost()始终为true,因此$this->$form->isValid($formData)也将成为现实,这意味着您可以在圈子中四处走动。

我知道以下内容与您的方法有很大不同,但我认为这是Zend 1控制器更常规的关注点分离。

// ... SomeController.php

  public function getLoginForm();

  public function getSignupForm();

  protected function authenticate($username, $password) 
  {
    $authAdapter = new My_Auth_Adapter();
    $authAdapter->setTableName('user')
                ->setIdentity($username)
                ->setCredential($password)
                ->setIdentityColumn('username')
                ->setCredentialColumn('password');
    $result = $authAdapter->authenticate();

    return ($result->isValid()) ? true : false;
  }

  public function indexAction()
  {
    $form = $this->getLoginForm();
    $request = $this->getRequest();

    if ($request->isPost()) {
      if ($form->isValid($request->getPost())) {

        if ($this->authenticate($form->getValue('username'), $form->getValue('username'))) {
          $this->redirect('/members'); // Successfully logged in
        }
      }
    }
    $this->view->form = $form;
  }

  public function signupAction()
  {
    // stuff only for signups! 
  }

编辑详细说明:forward()是控制器操作助手。它的工作只是修改Zend_Controller_Request_Http实例。 Zend_Controller_Request_Http类是在控制器中调用$this->getRequest()时返回的类。

Request实例封装了对$_POST$_GET的所有访问权限,然后将其存储为对象中的值。 $request->setParam('someparam', 123)之类的调用设置或获取这些值,而不是$_POST['someparam']$_GET['someparam']的标准直接访问权限。

特殊情况包括值modulecontrolleractiondispatched。这些是Zend_Controller_Front Dispatcher 在尝试确定实例化的正确控制器和执行的操作方法时使用的密钥。

dispatch loop如何运作的简化示例:

while(! $request->isDispatched()) {

  $request->setDispatched(true);

  // If at any point here we change setDispatched(true)
  // perhaps in a controller action with a call to forward()
  // then the whole dispatch loop will be called again
  // perhaps creating a different controller

  $controllerName = $request->getControllerName();
  $actionName = $request->getActionName();

  $controller = new $controllerName();
  $controller->$actionName();

}

答案 1 :(得分:0)

在else块中:

$this->_redirect($this->url(array('login' => $formData['username'], 'nameOfYourRoute'));

在您的路线中添加了一个新的获取变量'login',并使用此变量填充您的表单登录信息。