【问题标题】:Magento: Extending Customer Account Controller to add actions to the forgot password stepsMagento:扩展客户帐户控制器以向忘记密码的步骤添加操作
【发布时间】:2010-09-23 01:55:45
【问题描述】:

我们正在尝试向 AccountController 添加几个操作,以便在忘记密码发布操作之后添加另一个操作。问题是如果我们将操作添加到 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 调用父级,但也不确定这是否是正确的方法。

【问题讨论】:

    标签: redirect magento controller


    【解决方案1】:

    所以这就是我们所做的,我们得到了标志并检查了动作是否有无调度标志。然后我们取消设置,清除标头并重置响应代码。

    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);
        }
    }
    

    【讨论】:

    • 唯一的问题是,因为它调用 session->authenticate 方法,它会设置 beforeAuthUrl,当凭据不正确时会破坏登录过程。
    【解决方案2】:

    我需要做一些类似的事情, 我最终跳过了 Mage_Customer_AccountController 的 preDispatch 的原始实现。

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

    公共函数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(),它返回一个以管道分隔的操作列表,因此如果有人想要覆盖我自己的代码,添加另一个操作会容易得多。

    【讨论】:

      【解决方案3】:

      我做了如下

      1) 重写了 preDispatch 函数

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

      【讨论】:

      • 有兴趣知道 parent::preDispatch(); 实际上是做什么的。我必须先表扬它,但随后更愿意按照您的建议替换为Mage_Core_Controller_Front_Action::preDispatch();
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:
        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);
        }
        

        【讨论】:

          猜你喜欢
          • 2017-10-09
          • 2012-01-29
          • 1970-01-01
          • 2014-06-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多