2

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

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

<?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 并使用模型从数据库表中验证用户名/密码。

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

4

4 回答 4

6

请不要将以下内容视为即用型解决方案。我还添加了更多部分,当您开始管理登录时会发现它们很有用。您的主要部分应该是控制器的路由。我还保留了视图内容,除了其中的 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 到特定操作的映射是使用模块的 module.config.php 文件中定义的路由完成的。您应该为登录操作添加路由。这是更新的模块配置文件,其中包含注释块中的新代码。

<?php
return array(
    'controllers' => array(
        'invokables' => array(
            'Login\Controller\Login' => 'Login\Controller\LoginController',
        ),
    ),

    // 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' => 'Login\Controller\Login',
                        'action'     => 'index',
                    ),
                ),
            ),
        ),
    ),

    'view_manager' => array(
        'template_path_stack' => array(
            'login' => __DIR__ . '/../view',
        ),
    ),
);

路由的名称是“login”,类型为“segment”。分段路由允许您在 URL 模式(路由)中指定占位符,这些占位符将映射到匹配路由中的命名参数。在这种情况下,路由是/login[/:action][/:id],它将匹配任何以 /login 开头的 URL。下一个段将是一个可选的动作名称,最后下一个段将映射到一个可选的 id。方括号表示一个段是可选的。约束部分允许您确保段中的字符符合预期,因此您的操作仅限于以字母开头,随后的字符只能是字母数字、下划线或连字符。

控制器

现在您需要设置控制器。控制器是一个类,一般称为{Controller name}Controller。请注意,{Controller name} 必须以大写字母开头。此类位于模块的 Controller 目录中名为 {Controller name}Controller.php 的文件中。在您的情况下,这将类似于 module/Login/src/Login/Controller。每个动作都是控制器类中名为 {action name}Action 的公共方法。在您的情况下,{action name} 应以小写字母开头。

<?php
namespace Login\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class LoginController extends AbstractActionController
{
    public function authenticateAction($username, $password)
    {
        $params = array('driver' => 'driver',
                        'dbname' => 'name');

        $db = new DbAdapter($params);

        use Zend\Authentication\Adapter\DbTable 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('Login\Model\LoginTable');
        }
        return $this->loginTable;
    }
}

视图脚本

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

模块/登录/查看/登录/登录/authenticate.phtml`

该模型

在module/Login/src/Login/Model下创建一个名为Login.php的文件:

<?php
namespace Login\Model;

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

在module/Login/src/Login/Model目录中创建LoginTable.php文件,如下所示:

<?php
namespace Login\Model;

use Zend\Db\TableGateway\TableGateway;

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配置表网关并注入LoginTable

将此方法添加到module/Login中Module.php文件的底部。

<?php
namespace Login;

// Add these import statements:
use Login\Model\Login;
use Login\Model\LoginTable;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;

class Module
{
    // getAutoloaderConfig() and getConfig() methods here

    // Add this method:
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'Login\Model\LoginTable' =>  function($sm) {
                    $tableGateway = $sm->get('LoginTableGateway');
                    $table = new LoginTable($tableGateway);
                    return $table;
                },
                'LoginTableGateway' => function ($sm) {
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new Login());
                    return new TableGateway('login', $dbAdapter, null, $resultSetPrototype);
                },
            ),
        );
    }
}

最后,您需要配置 ServiceManager 以便它知道如何获取Zend\Db\Adapter\Adapter。使用以下代码修改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(
            'Zend\Db\Adapter\Adapter'
                    => 'Zend\Db\Adapter\AdapterServiceFactory',
        ),
    ),
);

你应该把你的数据库凭据放在config/autoload/local.php

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

您可能还会发现以下代码片段很有用(查看测试演示):

https://github.com/zendframework/zf2

于 2012-11-15T09:31:47.883 回答
0

你在一个问题中有几个问题。从学习如何验证密码的 Zend_Auth 开始,学习如何从请求中检索参数的 Zend_Controller,学习如何发送这些参数的 Zend_Form,学习如何将一些 js 与应用程序的其余部分相关联的 Zend_View。

简而言之,密码和用户名通过表单发送,您的应用程序通过请求对象的 getParams 方法获取它们。

我没有太多的链接可以发给你,ZF2 的文档目前还不少。

于 2012-11-13T13:53:23.360 回答
0

它不是很清楚你在问什么,所以我要写一个通用的答案,它不会特定于 zend 框架,因为我不知道 zend 框架。但以下几点适用于任何用于身份验证的技术。

  1. 您将不得不对服务器执行正常形式的 POST。您可以通过使用发送 AJAX 帖子在 extjs 中实现这一点

    form.submit(options)
    

    standardSubmit : true或通过在表单上设置进行普通的 HTML 提交。两者的文档都在这里这里。正如文档中所引用的Ext.form.Panel

    尽管没有作为 FormPanel 的配置选项列出,但 FormPanel 类接受 Ext.form.Basic 类支持的所有配置选项,并在创建时将它们传递给内部 BasicForm。

  2. 出于安全原因,密码应以加密格式存储在数据库中。此外,出于同样的安全原因,从数据库中解密存储的密码后,不应在代码中比较密码。因此,认证的标准查询就像

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

    传递给上述查询的密码也应该被加密。上述查询的结果应确定用户是否已成功通过身份验证。如果查询返回 0 结果,则验证失败。此外,使用上述样式的优点是您有一个用户对象,您可以将其与会话关联,而无需进行额外的查询。

因此,以下应该是这样的:

  1. 邮政
  2. 控制器捕获请求
  3. 检索用户名密码
  4. 通行证服务
  5. 服务调用加密器并获取加密密码
  6. 将用户名和加密密码传递给 DAO
  7. DAO 运行查询并返回结果服务
  8. 服务决定用户是否通过身份验证并将决定传递给控制器
  9. 控制器向用户发送适当的响应

我希望这回答了你的问题。

于 2012-11-15T06:32:39.210 回答
0

ZfcUser模块有一个登录验证的工作实现。它是ZF-Commons模块组的一部分,因此您也可以打赌它正在被积极维护。

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

于 2013-04-05T04:15:03.650 回答