PreDispatch Zend Framework nasıl yönlendirme mi?

3 Cevap php

Ben kullanıcı her denetleyicisi açtıysa kontrol ettikten sonra preDispatch in _forward() kullanmak istiyorum.

Senaryo oldukça kolaydır: Kullanıcı oturum değil ise, aynı kontrolör ya da başka bir denetleyici ya loginAction iletilmelidir.

Sevk işlemi preDispatch tekrar çağırarak, tekrar başlar ve yönlendirme tekrar herşeyi başlamak gibi bu, sonsuz bir döngüye neden olur.

Ben ile gelip başardı tek çözüm loginAction zaten istek ayarlanmış olup olmadığını kontrol etmek oldu.

Yani benim soru nasıl gelişmiş geliştirici bu sorunu ele istiyorsunuz, nedir?

UPDATE Just after hitting the send button, the ghost of the holy awareness came across ;) Another idea would be to build a LoginController to handle the login request. Or is there an even better way?

3 Cevap

Ben siteleri korumak için Zend_Controller_Plugin ve AuthController bir arada kullanın. Bu nedenle ılımlı karmaşıklık, şifre sıfırlar, zorunlu şifre değişiklikleri ve otomatik hesap kilitleme destekler.

Ben Doktrini kullanmak, yani bu tabii ki sadece kesmek ve uygulama içine yapıştırılan olamaz, ancak minimal değişiklikler ile çalışması gerektiğini unutmayın. Benim uygulamaya özgü birkaç yöntem kaldırıldı, ancak tüm genel doğrulama foo var.

Plugin

<?php
class Hobo_Controller_Plugin_Auth extends Zend_Controller_Plugin_Abstract
{
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $auth = Zend_Auth::getInstance();
        if ($auth->hasIdentity()) {
            if ('logout' != $request->getActionName()) {
                if (! $request->getParam('force_password_change')
                    && $this->_checkPasswordExpiry($auth->getIdentity()->username)
                ) {
                    $request->setParam('force_password_change', true);
                    $request->setModuleName('default')
                        ->setControllerName('auth')
                        ->setActionName('change-password');
                }
            }
        } else {
            // Defer more complex authentication logic to AuthController
            if ('auth' != $this->getRequest()->getControllerName()) {
                $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
                $redirector->gotoSimple('restricted', 'auth');
            }
        }
    }

    protected function _checkPasswordExpiry($username)
    {
        // Look up user and return true if password is expired
    }
}

AuthController

<?php

class AuthController extends Zend_Controller_Action
{
    public function init()
    {
        $this->_auth = Zend_Auth::getInstance();

        $this->_errorMessenger = new Zend_Controller_Action_Helper_FlashMessenger();
        $this->_errorMessenger->setActionController($this)->init();
        $this->_errorMessenger->setNamespace('error');

        $this->_noticeMessenger = new Zend_Controller_Action_Helper_FlashMessenger();
        $this->_noticeMessenger->setActionController($this)->init();
        $this->_noticeMessenger->setNamespace('notice');

        $this->view->errors = $this->_errorMessenger->getMessages();
        $this->view->notices = $this->_noticeMessenger->getMessages();
    }

    public function preDispatch()
    {
        if (! $this->_auth->hasIdentity()) {
            if (! in_array($this->_request->getActionName(), array(
                    'logout', 'identify', 'forgot-password', 'reset-password', 'restricted'))
                ) {
                $this->_redirect('/auth/restricted');
            }
        }
    }

    public function restrictedAction()
    {
        // Shows access restricted page
    }

    public function logoutAction()
    {
        $this->_auth->clearIdentity();
        Zend_Session::destroy();
        $this->_redirect('/');
    }

    public function identifyAction()
    {
        if ($this->_request->isPost()) {
            $username = $this->_getParam('username');
            $password = $this->_getParam('password');

            if (empty($username) || empty($password)) {
                $this->_flashError('Username or password cannot be blank.');
            } else {
                $user = new dUser();
                $result = $user->login($username, $password);

                if ($result->isValid()) {
                    $user->fromArray((array) $this->_auth->getIdentity());

                    if ($this->_getParam('changepass') || $user->is_password_expired) {
                        $this->_redirect('auth/change-password');
                        return;
                    }
                    $this->_doRedirect($user);
                    return;
                } else {
                    $this->_doFailure($result->getIdentity());
                }
            }
        }
        $this->_redirect('/');
    }

    public function changePasswordAction()
    {
        if ($this->_request->isPost()) {
            $username = $this->_auth->getIdentity()->username;
            $formData = $this->_request->getParams();

            if (empty($formData['password'])
                || empty($formData['new_password'])
                || empty($formData['confirm_password'])
            ) {
                $this->_flashError('Password cannot be blank.');
                $this->_redirect('auth/change-password');
            } elseif ($formData['new_password'] !== $formData['confirm_password']) {
                $this->_flashError('Password and confirmation do not match.');
                $this->_redirect('auth/change-password');
            } else {
                $user = new dUser();
                $result = $user->login($username, $formData['password']);

                if ($result->isValid()) {

                    $user->updatePassword($username, $formData['new_password']);
                    $this->_flashNotice('Password updated successfully!');
                    $this->_redirect('/');
                } else {
                    $this->_flashError('Invalid username or password!');
                    $this->_redirect('auth/change-password');
                }
            }

        }

        if ($this->_getParam('force_password_change')) {
            $this->view->notice = 'Your password has expired. You must change your password to continue.';
        }
    }

    public function forgotPasswordAction()
    {
        if ($this->_request->isPost()) {
            // Pseudo-random uppercase 6 digit hex value
            $resetCode = strtoupper(substr(sha1(uniqid(rand(),true)),0,6));

            Doctrine_Query::create()
                ->update('dUser u')
                ->set('u.reset_code', '?', array($resetCode))
                ->where('u.username = ?', array($this->_getParam('username')))
                ->execute();

            $this->_doMail($this->_getParam('username'), $resetCode);

            $this->_flashNotice("Password reset request received.");
            $this->_flashNotice("An email with further instructions, including your <em>Reset Code</em>, has been sent to {$this->_getParam('username')}.");
            $this->_redirect("auth/reset-password/username/{$this->_getParam('username')}");
        }
    }

    public function resetPasswordAction()
    {
        $this->view->username = $this->_getParam('username');
        $this->view->reset_code = $this->_getParam('reset_code');

        if ($this->_request->isPost()) {
            $formData = $this->_request->getParams();
            if (empty($formData['username']) || empty($formData['reset_code'])) {
                $this->_flashError('Username or reset code cannot be blank.');
                $this->_redirect('auth/reset-password');
            } elseif ($formData['new_password'] !== $formData['confirm_password']) {
                $this->_flashError('Password and confirmation do not match.');
                $this->_redirect('auth/reset-password');
            } else {
                $user = new dUser();
                $result = $user->loginWithResetCode($formData['username'], $formData['reset_code']);

                if ($result->isValid()) {
                    $user->updatePassword($result->getIdentity(), $formData['new_password']);

                    $user->fromArray((array) $this->_auth->getIdentity());

                    $this->_flashNotice('Password updated successfully!');
                    $this->_doRedirect($user);
                } else {
                    $this->_doFailure($result->getIdentity());
                    $this->_redirect('auth/reset-password');
                }
            }
        }
    }

    protected function _doRedirect($user)
    {
        $this->_helper->Redirector->gotoUserDefault($user);
    }

    protected function _flashError($message)
    {
        $this->_errorMessenger->addMessage($message);
    }

    protected function _flashNotice($message)
    {
        $this->_noticeMessenger->addMessage($message);
    }

    protected function _doFailure($username)
    {
        $user = Doctrine_Query::create()
            ->from('dUser u')
            ->select('u.is_locked')
            ->where('u.username = ?', array($username))
            ->fetchOne();

        if ($user->is_locked) {
            $this->_flashError('This account has been locked.');
        } else {
            $this->_flashError('Invalid username or password');
        }
    }
}

Alternatif aşağıdaki kullanabilirsiniz:

  $request->setParam('skippredispatch',true);
  $this->_forward('index');

Controller ve sonra [önce] Bu

// If overwriting jump the pre-dispatchy bits
if ($request->getParam('skippredispatch')){
  $request->setParam('skippredispatch',null);
  return;
}

Etkili cezası çalışmak gibi görünüyor predispatch döngü atlama.

Bu işlem herhangi bir eylem olabilir, ama neden LoginController değil LoginAction veya indexAction?

  1. Bulunan: kimliğinde bir giriş için kontrol? endeksi yönlendirme
  2. Sonrası params Giriş: bulundu? doğrulamak, set kimlik veya set hata iletileri
  3. Baskı formu

Edit: gerçek sorunu fark çok yorgun oldum olabilir. Böyle protected $authNeeded = true; gibi her giriş-korumalı denetleyici bir korumalı / özel üye, gibi bir şey ile başlar, ve Zend_Controller_Action::init() bunun için kontrol ediyorum. Bu tekrarlanan kod neden olabilir, bu yüzden başka bir seçenek sadece tüm giriş-korumalı kontrolör uzanan AuthNeededController bu kod gerçekleştirmek olacaktır.