使用Zend模型和控制器实现登录身份验证



我正在使用Zend 2.0,我从未将ExtJ与Zend结合使用。

这是我的extjs代码在viev/login/index.phtml中:

<?php $this->inlineScript()->captureStart() ?>
var LoginWindow
Ext.onReady(function() {
    LoginWindow = new Ext.create('Ext.window.Window',{
        title: 'Login',
        closable: false,
        draggable: false,
        resizable: false,
        width: 370,
        items: [
            Ext.create('Ext.form.Panel', {
                id: 'LoginForm',
                bodyPadding: 5,
                width: 350, 
                url: '/',
                layout: 'anchor',
                defaults: {
                    anchor: '100%'
                },
                // The fields
                defaultType: 'textfield',
                items: [{
                    fieldLabel: 'Username',
                    name: 'user',
                    allowBlank: false
                },{
                    fieldLabel: 'Password',
                    inputType: 'password',
                    name: 'pw',
                    allowBlank: false
                }],
                // Reset and Submit buttons
                buttons: [{
                    text: 'Reset',
                    handler: function() {
                        this.up('form').getForm().reset();
                    }
                },
                {
                    text: 'Submit',
                    formBind: true,
                    disabled: true,
                    handler: function() {
                        var form = this.up('form').getForm();
                    }
                }]
            })
        ]
    });
    Ext.getBody().mask()
    LoginWindow.show()  
});
<?php $this->inlineScript()->captureEnd() ?>

现在,我不确定如何将用户名/密码发送到logincontroller.php并使用模型从数据库表中验证用户名/密码。

任何示例或可能的解决方案都会真正有所帮助。

请不要将以下内容视为准备使用解决方案。我还添加了更多的部分,当您开始管理登录时,您会发现有用。您的主要部分应该是路由控制器。我还借鉴了视图内容,除了它的extjs部分。无论如何,我希望这对您有帮助。

首先,您的表格中有一些问题。尝试以下一个

var loginWindow;
Ext.onReady(function() {
    loginWindow = new Ext.create('Ext.window.Window',{
        title: 'Login',
        closable: false,
        draggable: false,
        resizable: false,
        width: 370,
        modal: true,
        items: [
            Ext.create('Ext.form.Panel', {
                id: 'LoginForm',
                bodyPadding: 5,
                width: 350, 
                layout: 'anchor',
                defaults: {
                    anchor: '100%'
                },
                defaultType: 'textfield',
                items: [{
                    fieldLabel: 'Username',
                    name: 'user',
                    allowBlank: false
                },{
                    fieldLabel: 'Password',
                    inputType: 'password',
                    name: 'pw',
                    allowBlank: false
                }],
                url: 'Login/Auth', // first one should be your controller, second one the controller action (this one need to accept post)
                buttons: [
                    {
                        text: 'Reset',
                        handler: function() {
                            this.up('form').getForm().reset();
                        }
                    },
                    {
                        text: 'Submit',
                        formBind: true,
                        disabled: true,
                        handler: function() {
                            var form = this.up('form').getForm();
                            if (form.isValid()) {
                                form.submit({
                                    success: function(form, action) {
                                       Ext.Msg.alert('Success', 'Authenticated!');
                                    },
                                    failure: function(form, action) {
                                        Ext.Msg.alert('Failed', 'Authentication Failed');
                                    }
                                });
                            }
                        }
                    }
                ]
            })
        ]
    }).show();
    // Ext.getBody().mask(); <- modal property does the same
});

现在到ZF2

路由

该应用程序的每个页面都被称为一个动作,并将操作分组为模块中的控制器。因此,您通常会将相关操作分组为控制器。

使用模块模块中定义的路由来完成URL对特定操作的映射。您应该添加登录操作的路由。这是在评论块中具有新代码的更新的模块配置文件。

<?php
return array(
    'controllers' => array(
        'invokables' => array(
            'LoginControllerLogin' => 'LoginControllerLoginController',
        ),
    ),
    // The following section is new and should be added to your file
    'router' => array(
        'routes' => array(
            'login' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'    => '/login[/:action][/:username][/:password]',
                    'constraints' => array(
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'username' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'password' => '[a-zA-Z][a-zA-Z0-9_-]*',
                    ),
                    'defaults' => array(
                        'controller' => 'LoginControllerLogin',
                        'action'     => 'index',
                    ),
                ),
            ),
        ),
    ),
    'view_manager' => array(
        'template_path_stack' => array(
            'login' => __DIR__ . '/../view',
        ),
    ),
);

该路由的名称是"登录",并具有"段"类型。该段路由允许您在URL模式(路由)中指定占位符,该图案将映射到匹配路由中的命名参数。在这种情况下,路由为/login [/:action] [/:ID] ,它将匹配任何始于/登录的URL。下一个段将是一个可选的操作名称,然后最后一个段将映射到可选的ID。方括号表明一个段是可选的。"约束"部分允许您确保段中的字符如预期的,因此您的动作有限,可以从字母开始,然后随后的字符仅为字母数字,下划线或连字符。

控制器

现在您需要设置控制器。控制器是通常称为{Controller Name}控制器的类。请注意,{控制器名称}必须从大写字母开始。该类生活在模块的控制器目录中的名为{Controller name} Controller.php的文件中。在您的情况下,将是模块/登录/src/login/Controller之类的东西。每个操作都是命名为{Action Name}操作的控制器类中的公共方法。在您的情况下{行动名称}应从较低的案例字母开始。

<?php
namespace LoginController;
use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;
class LoginController extends AbstractActionController
{
    public function authenticateAction($username, $password)
    {
        $params = array('driver' => 'driver',
                        'dbname' => 'name');
        $db = new DbAdapter($params);
        use ZendAuthenticationAdapterDbTable as AuthAdapter;
        // Oversimplified example without even hashing the password
        $adapter = new AuthAdapter($db,
                                   'Logins',
                                   'username',
                                   'password'
                                   );
        // get select object (by reference)
        $this->_adapter->setIdentity($username);
        $this->_adapter->setCredential($password);
        $result = $adapter->authenticate();
        if($result->isValid()) {
            // authenticated
        }
    }
    protected $loginTable;
    public function getLoginTable()
    {
        if (!$this->loginTable) {
            $sm = $this->getServiceLocator();
            $this->loginTable = $sm->get('LoginModelLoginTable');
        }
        return $this->loginTable;
    }
}

视图脚本

这些文件将由DefaultViewStrategy执行,并将传递从Controller Action方法返回的任何变量或视图模型。这些视图脚本存储在我们模块的视图目录中,以控制器命名。立即创建这四个空文件:

模块/login/view/login/login/authenticate.phtml`

模型

模块/login/src/login/model 下创建一个名为 login.php 的文件:

<?php
namespace LoginModel;
class Login
{
    public $id;
    public $username;
    public $password;
    public function exchangeArray($data)
    {
        $this->id     = (isset($data['id'])) ? $data['id'] : null;
        $this->username = (isset($data['username'])) ? $data['username'] : null;
        $this->password  = (isset($data['password'])) ? $data['password'] : null;
    }
}

创建您的 logintable.php 文件 module/login/login/src/login/model 目录如下:

<?php
namespace LoginModel;
use ZendDbTableGatewayTableGateway;
class LoginTable
{
    protected $tableGateway;
    public function __construct(TableGateway $tableGateway)
    {
        $this->tableGateway = $tableGateway;
    }
    public function fetchAll()
    {
        $resultSet = $this->tableGateway->select();
        return $resultSet;
    }
    public function getLogin($id)
    {
        $id  = (int) $id;
        $rowset = $this->tableGateway->select(array('id' => $id));
        $row = $rowset->current();
        if (!$row) {
            throw new Exception("Could not find row $id");
        }
        return $row;
    }
    public function saveLogin(Login $login)
    {
        $data = array(
            'username' => $login->password,
            'password'  => $login->username,
        );
        $id = (int)$login->id;
        if ($id == 0) {
            $this->tableGateway->insert($data);
        } else {
            if ($this->getLogin($id)) {
                $this->tableGateway->update($data, array('id' => $id));
            } else {
                throw new Exception('Form id does not exist');
            }
        }
    }
    public function deleteLogin($id)
    {
        $this->tableGateway->delete(array('id' => $id));
    }
}

使用ServiceManager配置表网关并注入到日志上

module.php 文件的底部添加此方法模块/login

<?php
namespace Login;
// Add these import statements:
use LoginModelLogin;
use LoginModelLoginTable;
use ZendDbResultSetResultSet;
use ZendDbTableGatewayTableGateway;
class Module
{
    // getAutoloaderConfig() and getConfig() methods here
    // Add this method:
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'LoginModelLoginTable' =>  function($sm) {
                    $tableGateway = $sm->get('LoginTableGateway');
                    $table = new LoginTable($tableGateway);
                    return $table;
                },
                'LoginTableGateway' => function ($sm) {
                    $dbAdapter = $sm->get('ZendDbAdapterAdapter');
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new Login());
                    return new TableGateway('login', $dbAdapter, null, $resultSetPrototype);
                },
            ),
        );
    }
}

最后,您需要配置ServiceManager,以便知道如何获得 zend db adapter adapter adapter 。modify config/autoLoad/global.php ,带有以下代码

<?php
return array(
    'db' => array(
        'driver'         => 'Pdo',
        'dsn'            => 'mysql:dbname=zf2tutorial;host=localhost',
        'driver_options' => array(
            PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES 'UTF8''
        ),
    ),
    'service_manager' => array(
        'factories' => array(
            'ZendDbAdapterAdapter'
                    => 'ZendDbAdapterAdapterServiceFactory',
        ),
    ),
);

您应该将数据库凭据放在 config/autoLoad/local.php

<?php
return array(
    'db' => array(
        'username' => 'YOUR USERNAME HERE',
        'password' => 'YOUR PASSWORD HERE',
    ),
);

您还可以找到以下代码片段有用(看看 tests demos ):

https://github.com/zendframework/zf2

您在一个问题中有几个问题。首先研究zend_auth的如何验证密码,zend_controller如何从请求中检索参数,zend_form,zend_form有关如何发送这些参数,zend_view,zend_view如何将某些j与您的其余的应用相关联。

。 简而

我没有太多的链接可以发送给您,ZF2的文档目前很少。

不太清楚您要问什么,所以我要编写一个通用的答案,这对Zend Framework并不具体,因为我不知道Zend Framework。但是以下几点适用于用于身份验证的任何技术。

  1. 您必须对服务器进行正常表单。你可以通过使用

    发送AJAX帖子,在ExtJ中实现了这一点
    form.submit(options)
    

    或通过设置standardSubmit : true在表格。两者的文档都在这里&amp;这里。作为在Ext.form.Panel

    的文档中引用

    尽管未列出为FormPanel的配置选项,但 FormPanel类接受所有配置选项 Extert.Form.Basic类,并将其传递到内部 创建基本形式。

  2. 密码应以加密格式存储在DB中安全原因。另外,出于相同的安全原因,密码解密存储后,不应在代码中比较来自DB的密码。因此,用于身份验证的标准查询就像

    select * from users where username='username' and password='password'
    

    也应加密传递给上述查询的密码。这上述查询的结果应确定用户是否具有已成功验证。如果查询返回0结果,然后身份验证失败了。另外,使用的优点以上样式是您拥有一个可以可以的用户对象与会话相关联而无需进行额外的查询。

因此,以下是这样的事情:

  1. 帖子
  2. 控制器捕获请求
  3. 检索用户名密码
  4. 传递到服务
  5. 服务致电加密人并获取加密密码
  6. 将用户名和加密密码传递到dao
  7. dao运行查询并返回结果服务
  8. 服务决定用户是否经过身份验证,并将决定权转换为控制器
  9. 控制器向用户发送适当的响应

我希望这可以回答您的问题。

ZFCUSER模块具有登录功能的工作实现。它是ZF-Commons组模块组的一部分,因此您也可以积极保留它。

非常适合参考或直接使用。

最新更新