PHPEye开源社区 » Zend Framework 使用讨论 » 用Zend Framework做登录验证(转载)
《Programming PHP》第二版上市
2008-7-9 10:39 c61811
用Zend Framework做登录验证(转载)

原文:[url=http://weierophinney.net/matthew/archives/165-Login-and-Authentication-with-Zend-Framework.html][color=#800080]http://weierophinney.net/matthew/archives/165-Login-and-Authentication-with-Zend-Framework.html[/color][/url]
我收集到很多如何在Zend Framework控制身份认证的问题。典型的问题是他们不知道如何结合:
[list][*]一个认证适配器[*]一个登陆表单[*]一个login/logout的controller动作[*]检测提交请求的验证用户[/list]它不是很可怕,但是它需要知道不同MVC块之间如何搭配在一起,和如何使用Zend_Auth。让我们看一下。

Authentication Adapter【认证适配器】为了使这些工作,你需要一个[url=http://framework.zend.com/manual/en/zend.auth.html#zend.auth.introduction.adapters][color=#0000ff]authentication adapter[/color][/url]。这个例子不是针对那个的,而是根据文档需要的,你需要给予你的站。我将做一个假设,就是你的认证器需要用户名密码来作为验证凭据。
我们的登录controller将用这个适配器,但是简单的需要一个占位符来收回它。

Login Form【登录表单】登录表单本身非常的简单。你可以创建一些基本的认证规则 使你可以保护数据库或者其他的服务,但是否则保持事情相对简单。为了手册的目的,我们定义了一下标准:
[list][*]用户名只能是字母,在3-20个之间。[*]密码必须是数字组成的,在6-20个之间。[/list]表单如下:
[align=left]
[b]class[/b] LoginForm extends Zend_Form
[color=#66cc66]{[/color]
public [b]function[/b] init[color=#66cc66]([/color][color=#66cc66])[/color]
[color=#66cc66]{[/color]
[color=#0000ff]$username[/color] = [color=#0000ff]$this[/color]->[color=#006600]addElement[/color][color=#66cc66]([/color][color=#ff0000]'text'[/color], [color=#ff0000]'username'[/color], [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color]
[color=#ff0000]'filters'[/color] => [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#ff0000]'StringTrim'[/color], [color=#ff0000]'StringToLower'[/color][color=#66cc66])[/color],
[color=#ff0000]'validators'[/color] => [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color]
[color=#ff0000]'Alpha'[/color],
[url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#ff0000]'StringLength'[/color], [b]false[/b], [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#cc66cc]3[/color], [color=#cc66cc]20[/color][color=#66cc66])[/color][color=#66cc66])[/color],
[color=#66cc66])[/color],
[color=#ff0000]'required'[/color] => [b]true[/b],
[color=#ff0000]'label'[/color] => [color=#ff0000]'Your username:'[/color],
[color=#66cc66])[/color][color=#66cc66])[/color];

[color=#0000ff]$password[/color] = [color=#0000ff]$this[/color]->[color=#006600]addElement[/color][color=#66cc66]([/color][color=#ff0000]'password'[/color], [color=#ff0000]'password'[/color], [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color]
[color=#ff0000]'filters'[/color] => [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#ff0000]'StringTrim'[/color][color=#66cc66])[/color],
[color=#ff0000]'validators'[/color] => [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color]
[color=#ff0000]'Alnum'[/color],
[url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#ff0000]'StringLength'[/color], [b]false[/b], [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#cc66cc]6[/color], [color=#cc66cc]20[/color][color=#66cc66])[/color][color=#66cc66])[/color],
[color=#66cc66])[/color],
[color=#ff0000]'required'[/color] => [b]true[/b],
[color=#ff0000]'label'[/color] => [color=#ff0000]'Password:'[/color],
[color=#66cc66])[/color][color=#66cc66])[/color];

[color=#0000ff]$login[/color] = [color=#0000ff]$this[/color]->[color=#006600]addElement[/color][color=#66cc66]([/color][color=#ff0000]'submit'[/color], [color=#ff0000]'login'[/color], [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color]
[color=#ff0000]'required'[/color] => [b]false[/b],
[color=#ff0000]'ignore'[/color] => [b]true[/b],
[color=#ff0000]'label'[/color] => [color=#ff0000]'Login'[/color],
[color=#66cc66])[/color][color=#66cc66])[/color];

[color=#808080][i]// We want to display a 'failed authentication' message if necessary;[/i][/color]
[color=#808080][i]// we'll do that with the form 'description', so we need to add that[/i][/color]
[color=#808080][i]// decorator.[/i][/color]
[color=#0000ff]$this[/color]->[color=#006600]setDecorators[/color][color=#66cc66]([/color][url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color]
[color=#ff0000]'FormElements'[/color],
[url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#ff0000]'HtmlTag'[/color], [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#ff0000]'tag'[/color] => [color=#ff0000]'dl'[/color], [color=#ff0000]'class'[/color] => [color=#ff0000]'zend_form'[/color][color=#66cc66])[/color][color=#66cc66])[/color],
[url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#ff0000]'Description'[/color], [url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color][color=#ff0000]'placement'[/color] => [color=#ff0000]'prepend'[/color][color=#66cc66])[/color][color=#66cc66])[/color],
[color=#ff0000]'Form'[/color]
[color=#66cc66])[/color][color=#66cc66])[/color];
[color=#66cc66]}[/color]
[color=#66cc66]}[/color][/align]
Login Controller【登录控制】现在,让我我们创建一个控制器来操纵登录和退出动作。典型的流程如下:
[list][*]用户点击登录表单[*]用户提交登录表单[*]控制器处理表单[list][*]确认错误,重新显示错误和错误信息。[*]成功确认重定向到主页[/list][*]已经登录的用户重定向到主页[*]退出动作退出用户重定向到登录表单[/list]这个LoginController将使用你选择的登陆器,既这个登录表单。We will pass to the login form constructor the form action and method (since we now know what they will be for this usage of the form).。当我们获得一个有效值,我们将传递他们到我们的验证器中。
创建控制器. 首先, 我们将创建表达那存取和验证适配器.
[align=left]
[b]class[/b] LoginController extends Zend_Controller_Action
[color=#66cc66]{[/color]
public [b]function[/b] getForm[color=#66cc66]([/color][color=#66cc66])[/color]
[color=#66cc66]{[/color]
[color=#b1b100]return[/color] [b]new[/b] LoginForm[color=#66cc66]([/color][url=http://www.php.net/array][color=#000066]array[/color][/url][color=#66cc66]([/color]
[color=#ff0000]'action'[/color] => [color=#ff0000]'/login/process'[/color],
[color=#ff0000]'method'[/color] => [color=#ff0000]'post'[/color],
[color=#66cc66])[/color][color=#66cc66])[/color];
[color=#66cc66]}[/color]

public [b]function[/b] getAuthAdapter[color=#66cc66]([/color][url=http://www.php.net/array][color=#000066]array[/color][/url] [color=#0000ff]$params[/color][color=#66cc66])[/color]
[color=#66cc66]{[/color]
[color=#808080][i]// Leaving this to the developer...[/i][/color]
[color=#808080][i]// Makes the assumption that the constructor takes an array of [/i][/color]
[color=#808080][i]// parameters which it then uses as credentials to verify identity.[/i][/color]
[color=#808080][i]// Our form, of course, will just pass the parameters 'username'[/i][/color]
[color=#808080][i]// and 'password'.[/i][/color]
[color=#66cc66]}[/color]
[color=#66cc66]}[/color][/align]

2008-7-9 10:41 c61811
回复 #1 c61811 的帖子

其次, 在发送任何动作以前我们需要做以下认证:

如果用户已经被验证了,但是没有退出,重定向到主页。
如果用户没有被认证, 但是已经推出,重定向到登录页面
下面这个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();
}
}
Processing the form involves slightly more logic. 我们需要确认我们有一个提交请求 ,然后这个表单是有效的,并且最后这凭据也是有效的。


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

Okay, that's it for our login/logout routines. Let's look at the one associated view we have, the form:


<? // login/index.phtml ?>
<h2>Please Login</h2>
<?= $this->form ?>
如上.其实. Zend_Form写脚本很容易.

检验登录用户
最后的问题是: 如何确认一个用户是验证的和受限的?

如果你仔细看上面preDispatch()方法,你能够看到这个能做什么. Zend_Auth保存认证在session里,允许直接查询:


Zend_Auth::getInstance()->hasIdentity()
你可以用这个确认用户是否已经登录,如果没有可以重定向到登录页.你可以从用户对象中获取身份信息:


$identity = Zend_Auth::getInstance()->getIdentity();
这个可以放到一个helper里来在layout显示登陆状态, 例如:


/**
* 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>';
}
}

页: [1]


Powered by Discuz! Archiver 5.5.0  © 2001-2006 Comsenz Inc.