【问题标题】:Sencha Touch 2: Checking cookie on app launchSencha Touch 2:在应用启动时检查 cookie
【发布时间】:2013-11-14 00:02:27
【问题描述】:

我对使用 Sencha Touch 2 库进行开发完全陌生。我按照本教程帮助创建了一个简单的登录脚本 (http://miamicoder.com/2012/adding-a-login-screen-to-a-sencha-touch-application-part-2/)。我不确定的一件事是如何检查会话令牌是否存在于客户端,以便当他们返回应用程序时,登录屏幕不会显示他们是否已通过身份验证。

app.js

Ext.application({
    name: 'RecruitTalkTouch',
    views: ['Login', 'MainMenu'],
    controllers: ['Login'],
    launch: function () {
      Ext.Viewport.add([
        { xtype: 'loginview' },
        { xtype: 'mainmenuview' }
      ]);
    }
});

Login.js 控制器:

Ext.define('RecruitTalkTouch.controller.Login', {
  extend: 'Ext.app.Controller',
  config: {
    refs: {
      loginView: 'loginview',
      mainMenuView: 'mainmenuview'
    },
    control: {
      loginView: {
        signInCommand: 'onSignInCommand'
      },
      mainMenuView: {
        signOffCommand: 'onSignOffCommand'
      }
    }
  },
  onSignInCommand: function(view, username, password) {
    var me = this,
        loginView = me.getLoginView();

    if(username.length === 0 || password.length === 0) {
      loginView.showSignInFailedMessage('Please enter your username and password.');
      return;
    }

    loginView.setMasked({
      xtype: 'loadmask',
      message: 'Signing In...'
    });

    Ext.Ajax.request({
      url: 'http://localhost:3000/api/v1/sessions.json',
      method: 'POST',
      useDefaultXhrHeader: false,
      params: {
        login: username,
        password: password
      },
      success: function(resp) {
        var json = Ext.JSON.decode(resp.responseText);

        if(json.success === "true") {
          me.sessionToken = json.auth_token;
          me.signInSuccess();
        } else {
          me.signInFailure(json.message)
        }
      },
      failure: function(resp) {
        me.sessionToken = null;
        me.signInFailure('Login failed. Please try again');
      }
    });
  },
  signInSuccess: function() {
    console.log("Signed In");
    var loginView = this.getLoginView(),
        mainMenuView = this.getMainMenuView();

    loginView.setMasked(false);

    Ext.Viewport.animateActiveItem(mainMenuView, this.transition('slide', 'left'));
  },
  signInFailure: function(message) {
    var loginView = this.getLoginView();
    loginView.showSignInFailedMessage(message);
    loginView.setMasked(false);
  },
  transition: function(type, direction) {
    return { type: type, direction: direction };
  },
  onSignOffCommand: function() {
    var me = this;
    me.sessionToken = null;
    Ext.Viewport.animateActiveItem(this.getLoginView(), this.transition('slide', 'right'));
  }
});

Login.js 视图:

Ext.define('RecruitTalkTouch.view.Login', {
    extend: 'Ext.form.Panel',
    alias: "widget.loginview",
    requires: ['Ext.form.FieldSet', 'Ext.form.Password', 'Ext.Label', 'Ext.Button'],
    config: {
        title: 'Login',
        items: [
          {
            xtype: 'label',
            html: 'Login failed. Please enter the correct credentials.',
            itemId: 'signInFailed',
            hidden: true,
            hideAnimation: 'fadeOut',
            showAnimation: 'fadeIn'
          },
          {
            xtype: 'fieldset',
            title: 'Login',
            items: [
              {
                xtype: 'textfield',
                placeHolder: 'Username',
                itemId: 'userNameTextField',
                name: 'userNameTextField',
                required: true
              },
              {
                xtype: 'passwordfield',
                placeHolder: 'Password',
                itemId: 'passwordTextField',
                name: 'passwordTextField',
                required: true
              }
            ]
          },
          {
            xtype: 'button',
            itemId: 'logInButton',
            ui: 'action',
            padding: '10px',
            text: 'Log In'
          }
        ],
        listeners: [{
          delegate: '#logInButton',
          event: 'tap',
          fn: 'onLogInButtonTap'
        }]
    },
    onLogInButtonTap: function() {
      var me = this,
          usernameField = me.down('#userNameTextField'),
          passwordField = me.down('#passwordTextField'),
          label = me.down('#signInFailed'),
          username = usernameField.getValue(),
          password = passwordField.getValue();

      label.hide();

      var task = Ext.create('Ext.util.DelayedTask', function(){
        label.setHtml('');
        me.fireEvent('signInCommand', me, username, password);

        usernameField.setValue('');
        passwordField.setValue('');
      });

      task.delay(500);
    },
    showSignInFailedMessage: function(message) {
      var label = this.down('#signInFailed');
      label.setHtml(message);
      label.show();
    }
});

【问题讨论】:

    标签: extjs sencha-touch sencha-touch-2


    【解决方案1】:

    您可能会发现在服务器上添加一个检查功能来检查有效会话会更容易。即使 cookie 存在,也不意味着他们没有注销,会话 cookie 会随着每个请求来回发送。

    也就是说,如果您想从客户端访问 cookie,它们将作为单个字符串值附加到文档中。您可以通过 document.cookies 访问它们。我会查看 ExtJS cookie 实用程序的文档和来源,以获取有关如何在该字符串中查找 cookie 的一些灵感。

    Ext.util.Cookies Documentation

    Ext.util.Cookies Source

    基本上这个过程是遍历cookie字符串中的每个字母,取出一个子字符串到会话密钥名称的长度,看看它是否匹配,然后拉取下一个等号和分号之间的数据。然后你取消百分比编码值,你就可以开始了。

    编辑 要 ping 服务器,您只需在显示第一个视图之前在应用程序加载过程中的某处发出 Ajax 请求。我认为启动功能是一个非常自然的地方:

    Ext.application({
        name: 'App',
    
        requires: [],
        models: [],
        stores: [],
        views: [],
        controllers: [],
    
        ....
    
        launch: function () {
            //Check with the server
            Ext.Ajax.request({
                //Proxy Settings
                url: 'path/to/check/script.php',
                //Callbacks
                success: function (response, opts) {
                    // process server response here
                    response = Ext.JSON.decode(response.responseText);
                    if(response && response.success === true) {
                        //Load the normal first view
                        Ext.Viewport.add(Ext.create('App.view.Main');
                    } else {
                        //Load the login view
                        Ext.Viewport.add(Ext.create('App.view.LoginForm');
                    }
                },
                failure: function (response, opts) {
                    //Notify of network failure
                }
            });
        }
    });
    

    至于在服务器端的脚本中做什么,这取决于您正在使用什么语言进行开发以及您要针对什么进行身份验证。如果它只是一个用户名和密码的数据库,那么当用户第一次登录时,启动一个会话,并为他们的用户 ID 和密码存储一个会话变量。在检查功能中,首先检查当前会话是否存在,然后针对您的数据库重新进行身份验证,以确保它们仍然有效(以防您或其他人在会话仍然有效时取消了他们的帐户)。然后只需发回一个 json 响应,说明他们是否已登录,并包含使您的应用正常运行所需的任何相关用户信息。

    【讨论】:

    • 感谢您的建议!那么您是说在应用启动时,我应该 ping 服务器以确保用户已登录并检查 cookie?
    • 是的,ping 服务器是我经常做的并且会推荐的。如果您正在使用听起来像的会话,检查它们是否在服务器上登录确实会使用 cookie(它们每次都在 http 请求中来回发送)。服务器从 http 请求中的 cookie 中提取会话 ID,检查它是否仍在跟踪该 ID,以及它是否已过期。我确信这在一定程度上取决于语言/环境,但我很确定这是大多数 Web 开发堆栈中用户跟踪背后的总体思路。
    • 太棒了!非常感谢!无论如何,您可以提供一个在应用启动时 ping 服务器的示例?
    • 这正是我所做的。上面的例子是点击/ping 服务器。它正在向“path/to/check/script.php”发出 ajax 请求,然后根据请求中的会话显示登录表单或主应用程序。如果用户未登录,则发送 401 或其他错误状态。否则发送 200,并显示主视图。
    【解决方案2】:

    在 Sencha Touch 中使用:

    var cookiestr = document.cookie.split('; ');
    var cookieObjArr = new Array();
    
    for (var i=0; i<cookiestr.length; ++i)
    {
        if (i in cookiestr)
        {
            tmp = cookiestr[i].split('=');
            cookieObjArr.push({"key": tmp[0], "value": tmp[1]});
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-07
      • 1970-01-01
      • 1970-01-01
      • 2012-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多