开放的编程资料库

当前位置:我爱分享网 > PHP教程 > 正文

使用 Zend Framework 进行登录和身份验证

更新:本文现已提供法语版本,由FrédéricBlanc提供。

我已经回答了一些想知道如何在ZendFramework中处理身份验证和身份持久性的人提出的问题。典型的问题是他们不确定如何组合:

  • 身份验证适配器
  • 登录表单
  • 用于登录/注销操作的控制器
  • 在后续请求中检查经过身份验证的用户

这并不难,但确实需要了解MVC的各个部分如何组合在一起,以及如何使用Zend_Auth。让我们来看看。

身份验证适配器

要使所有这些工作正常,您需要一个身份验证适配器。我不打算对此进行详细说明,因为文档涵盖了它们,并且您的需求会因您的站点而异。但是,我假设您的身份验证适配器需要用户名和密码来进行身份验证。

我们的登录控制器将使用适配器,但只是有一个用于检索它的占位符。

登录表单

登录表单本身非常简单。您可以设置一些基本的验证规则,以防止数据库或其他服务命中,但要保持相对简单。出于本教程的目的,我们将定义以下标准:

  • 用户名只能是字母字符,并且必须包含3到20个字符
  • 密码必须只能是字母数字字符,并且必须是6到20个字符

表单看起来像这样:

class LoginForm extends Zend_Form
{
    public function init()
    {
        $username = $this->addElement('text', 'username', array(
            'filters'    => array('StringTrim', 'StringToLower'),
            'validators' => array(
                'Alpha',
                array('StringLength', false, array(3, 20)),
            ),
            'required'   => true,
            'label'      => 'Your username:',
        ));

        $password = $this->addElement('password', 'password', array(
            'filters'    => array('StringTrim'),
            'validators' => array(
                'Alnum',
                array('StringLength', false, array(6, 20)),
            ),
            'required'   => true,
            'label'      => 'Password:',
        ));

        $login = $this->addElement('submit', 'login', array(
            'required' => false,
            'ignore'   => true,
            'label'    => 'Login',
        ));

        // We want to display a 'failed authentication' message if necessary;
        // we'll do that with the form 'description', so we need to add that
        // decorator.
        $this->setDecorators(array(
            'FormElements',
            array('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form')),
            array('Description', array('placement' => 'prepend')),
            'Form'
        ));
    }
}

登录控制器

现在,让我们创建一个控制器来处理登录和注销操作。典型的流程是:

  • 用户点击登录表单
  • 用户提交表单
  • 控制器处理表单
    • 验证错误重新显示带有错误消息的表单
    • 成功验证重定向到主页
  • 登录用户被重定向到主页
  • 注销操作注销用户并重定向到登录表单
  • 李>

LoginController将使用您选择的身份验证适配器以及登录表单。我们将把表单和方法传递给登录表单构造函数(因为我们现在知道它们对于表单的这种用法是什么)。当我们有有效值时,我们会将它们传递给我们的身份验证适配器。

那么,让我们来创建控制器。首先,我们将为表单和身份验证适配器创建访问器。

class LoginController extends Zend_Controller_Action
{
    public function getForm()
    {
        return new LoginForm(array(
            'action' => '/login/process',
            'method' => 'post',
        ));
    }

    public function getAuthAdapter(array $params)
    {
        // Leaving this to the developer...
        // Makes the assumption that the constructor takes an array of 
        // parameters which it then uses as credentials to verify identity.
        // Our form, of course, will just pass the parameters 'username'
        // and 'password'.
    }
}

接下来,我们需要在派发任何操作之前进行一些检查,以确保:

  • 如果用户已经通过认证,但是没有请求退出,我们应该重定向到首页
  • 如果用户没有通过认证,但是已经请求退出,我们应该重定向到登录页面

下面的preDispatch()例程将为我们做这件事:

class LoginController extends Zend_Controller_Action
{
    // ...

    public function preDispatch()
    {
        if (Zend_Auth::getInstance()->hasIdentity()) {
            // If the user is logged in, we don't want to show the login form;
            // however, the logout action should still be available
            if ('logout' != $this->getRequest()->getActionName()) {
                $this->_helper->redirector('index', 'index');
            }
        } else {
            // If they aren't, they can't logout, so that action should 
            // redirect to the login form
            if ('logout' == $this->getRequest()->getActionName()) {
                $this->_helper->redirector('index');
            }
        }
    }
}

现在,我们需要做我们的登录表单。这是我们最简单的方法——我们只需检索表单并将其分配给视图:

class LoginController extends Zend_Controller_Action
{
    // ...

    public function indexAction()
    {
        $this->view->form = $this->getForm();
    }
}

处理表单涉及的逻辑稍微多一些。我们需要验证我们有一个发布请求,然后验证表单是否有效,最后验证凭据是否有效。

class LoginController extends Zend_Controller_Action
{
    // ...
    
    public function processAction()
    {
        $request = $this->getRequest();

        // Check if we have a POST request
        if (!$request->isPost()) {
            return $this->_helper->redirector('index');
        }

        // Get our form and validate it
        $form = $this->getForm();
        if (!$form->isValid($request->getPost())) {
            // Invalid entries
            $this->view->form = $form;
            return $this->render('index'); // re-render the login form
        }

        // Get our authentication adapter and check credentials
        $adapter = $this->getAuthAdapter($form->getValues());
        $auth    = Zend_Auth::getInstance();
        $result  = $auth->authenticate($adapter);
        if (!$result->isValid()) {
            // Invalid credentials
            $form->setDescription('Invalid credentials provided');
            $this->view->form = $form;
            return $this->render('index'); // re-render the login form
        }

        // We're authenticated! Redirect to the home page
        $this->_helper->redirector('index', 'index');
    }
}

最后,我们可以处理注销操作。这几乎和显示登录表单一样简单;我们只需从身份验证对象中清除身份,然后重定向:

class LoginController extends Zend_Controller_Action
{
    // ...

    public function logoutAction()
    {
        Zend_Auth::getInstance()->clearIdentity();
        $this->_helper->redirector('index'); // back to login page
    }
}

好的,这就是我们的登录/注销例程。让我们看一下我们拥有的一个关联视图,形式为:

<? // login/index.phtml ?>
<h2>Please Login</h2>
<?= $this->form ?>

就是这样。真的。Zend_Form使视图脚本变得简单。:-)

检查经过身份验证的用户

问题区的最后一部分是:如何判断用户是否已通过身份验证,如果没有则限制访问?

如果您仔细查看上面的preDispatch()方法,您就会明白这是如何完成的。Zend_Auth在会话中保留身份,允许您使用此构造直接查询它:

Zend_Auth::getInstance()->hasIdentity()

你可以用它来判断用户是否登录,如果没有登录则使用redirector重定向到登录页面。您也可以从auth对象中提取身份:

$identity = Zend_Auth::getInstance()->getIdentity();

这可以添加到帮助程序中以在您的布局中显示登录状态,例如:

/**
 * ProfileLink helper
 *
 * Call as $this->profileLink() in your layout script
 */
class My_View_Helper_ProfileLink
{
    public $view;

    public function setView(Zend_View_Interface $view)
    {
        $this->view = $view;
    }

    public function profileLink()
    {
        $auth = Zend_Auth::getInstance();
        if ($auth->hasIdentity()) {
            $username = $auth->getIdentity()->username;
            return '<a href=\"/profile' . $username . '\">Welcome, ' . $username .  '</a>';
        } 

        return '<a href=\"/login\">Login</a>';
    }
}

结论

Zend_Auth做了很多幕后工作,使在会话中持久化身份变得微不足道。将它与Zend_Form相结合,您就拥有了一个非常易于实施的检索和验证凭据的解决方案;在Zend_Controller组件中添加标准挂钩以在发送之前过滤操作,并且您可以根据身份验证状态轻松限制对应用程序的访问。

未经允许不得转载:我爱分享网 » 使用 Zend Framework 进行登录和身份验证

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏