Magento:扩展客户帐户控制器,为忘记密码步骤添加操作

时间:2010-09-23 01:55:46

标签: redirect magento controller

我们正在尝试向AccountController添加一些操作,以便在forgetpasswordpost操作之后添加另一个操作。问题是如果我们将操作添加到preDispatch路由以确保您不必登录它仍然重定向回登录页面。

public function preDispatch()
    {
        // a brute-force protection here would be nice

        parent::preDispatch();

        if (!$this->getRequest()->isDispatched()) {
            return;
        }

        $action = $this->getRequest()->getActionName();
        if (!preg_match('/^(create|login|logoutSuccess|forgotpassword|forgotpasswordpost|confirm|confirmation|newactionhere)/i', $action)) {
            if (!$this->_getSession()->authenticate($this)) {
                $this->setFlag('', 'no-dispatch', true);
            }
        } else {
            $this->_getSession()->setNoReferer(true);
        }
    }

这不起作用,因为我们首先调用父项运行它,但当然preg_match不匹配,它运行验证方法运行方法$ action-> getResponse() - > setRedirect($ url)当然会设置标题,当它返回到我们的代码时无关紧要,然后重定向。

我们可以删除对父进程的调用,但我不确定这是最好的方法,因为父进程调用它的父进程运行一些东西来设置布局区域,然后调用父方法。我想用Mage_Core_Controller_Front_Action调用父母,但不确定这是不正确的方法。

5 个答案:

答案 0 :(得分:4)

所以这就是我们所做的,我们得到了旗帜并检查了该行动是否具有不发送的标志。然后我们取消设置,清除标题并重置响应代码。

public function preDispatch()
{
    // a brute-force protection here would be nice

    parent::preDispatch();

    $action = $this->getRequest()->getActionName();

    // The parent preDispatch call will set:
    // 1. the 'no-dispatch' flag and set a
    // 2. a 'Location' header for a 302 redirect to the login page
    //    for any actions which are not on the list.
    // 3. a HTTP Response Code of 302 (temporary redirect).
    // We add additional actions securityquestion and securityquestionpost in our override below, but
    // we need to undo the settings which get set by the call to the parent above.
    if (preg_match('/^(securityquestion|securityquestionpost)/i', $action))
    {
        $flag = 'no-dispatch';

        if ($this->getFlag($action, $flag))
        {
              unset($this->_flags[$action][$flag]); // Remove the flag to unset it
              $this->getResponse()->clearHeader('Location'); // Remove Location header for redirect
              $this->getResponse()->setHttpResponseCode(200); // Set HTTP Response Code to OK

        }
    }

    if (!$this->getRequest()->isDispatched()) {
        return;
    }


    if (!preg_match('/^(create|login|logoutSuccess|forgotpassword|forgotpasswordpost|confirm|confirmation|securityquestion|securityquestionpost)/i', $action)) {
        if (!$this->_getSession()->authenticate($this)) {
            $this->setFlag('', 'no-dispatch', true);
        }
    } else {
        $this->_getSession()->setNoReferer(true);
    }
}

答案 1 :(得分:2)

我需要做同样的事, 我最后跳过了Mage_Customer_AccountController的preDispatch的原始实现。

所以在我的首要课程中我有:

public function validActions(){     return'create | login | logoutSuccess | forgotpassword | forgotpasswordpost | confirm | confirmation | mynewaction'; }

public function preDispatch()
{
    //I override this to add my new Action as a valid one.
    //this is also the reason why I call the grand parent and not parent class's preDispatch()
    // becase the default implementation does not enable to simply override the list of valid actions.

    // a brute-force protection here would be nice

    $par = get_parent_class($this);
    $gpar = get_parent_class($par);  
    $gpar::preDispatch();

    if (!$this->getRequest()->isDispatched()) {
        return;
    }

    $action = $this->getRequest()->getActionName();
    if (!preg_match('/^(' . $this->validActions() . ')/i', $action)) {
        if (!$this->_getSession()->authenticate($this)) {
            $this->setFlag('', 'no-dispatch', true);
        }
    } else {
        $this->_getSession()->setNoReferer(true);
    }
}

正如您所看到的,我还添加了一个validActions(),它返回一个以管道分隔的操作列表,因此如果有人想要覆盖我自己的代码,那么添加其他操作会更容易。

答案 2 :(得分:2)

我按照以下方式完成了

1)重写函数preDispatch

2)并替换代码parent :: preDispatch(); with Mage_Core_Controller_Front_Action :: preDispatch(); 。它的工作正常。但不确定这是否是正确的方法。

答案 3 :(得分:1)

我建议您在postDispatch上添加观察者,过滤accountController,然后设置_redirect。如果您需要更多信息,请告诉我。

答案 4 :(得分:0)

protected $_validActions = array('create','login','logoutSuccess','forgotpassword','forgotpasswordpost','confirm','confirmation');
protected $_customActions = array('customaction1', 'customaction2');

/**
 * Action predispatch
 *
 * Check customer authentication for some actions
 */
public function preDispatch()
{
    // a brute-force protection here would be nice

    $action = $this->getRequest()->getActionName();

    /**
     * If the requested action is a custom action, we can get around the parent class's 
     * action validation check by passing it an action it knows like 'login' for example.
     * 
     * We'll reset the action name in the request temporairily so that we don't have to deal with 
     * all the headers and flags that get set when an action check fails validation. This will also
     * allow us to avoid having the session->beforeAuthUrl getting set when session->authenticate(action) fails
     */
    if (preg_match('/^('.$this->_getCustomActions().')/i', $action))
    {
        $this->getRequest()->setActionName($this->_validActions[1]);
    }

    parent::preDispatch();

    /**
     * Parent check is complete, reset request action name to origional value
     */
    if ($action != $this->getRequest()->getActionName())
    {
        $this->getRequest()->setActionName($action);
    }

    if (!$this->getRequest()->isDispatched()) {
        return;
    }

    if (!preg_match('/^('.$this->_getValidActions().')/i', $action)) {
        if (!$this->_getSession()->authenticate($this)) {
            $this->setFlag('', 'no-dispatch', true);
        }
    } else {
        $this->_getSession()->setNoReferer(true);
    }

}

/**
 * Gets default action names and returns them as a pipe separated string
 *
 * @return string
 */
protected function _getValidActions()
{
    return implode("|", array_merge($this->_validActions, $this->_customActions));
}

/**
 * Gets custom action names and returns them as a pipe separated string
 *
 * @return string
 */
protected function _getCustomActions()
{
    return implode("|", $this->_customActions);
}