【问题标题】:Why does sencha ajax requests not send/store session cookie given by the server (sails)为什么 sencha ajax 请求不发送/存储服务器提供的会话 cookie(帆)
【发布时间】:2018-09-26 07:05:48
【问题描述】:

我有一个使用邮递员完美运行的系统,我可以 POST 到

localhost:1337/api/user/loginusernamepassword 在请求正文中设置。然后验证登录并允许我访问更多呼叫。 (并且反复致电localhost:1337/api/user/login 承认我已经记录并回复)。

当我检查服务器时,我注意到邮递员确实在我发出的每个请求中都发送了(htmlonly)cookie。

现在我尝试通过 sencha 6.5 modern 进行相同的登录。在某些控制器中,我有以下代码:

    const form = this.getView();
    if (form.isValid()) {
        const data = form.getValues();
        const u = 'http://localhost:1337/api/user/login'; //form.getUrl();
        debugger;
        Ext.Ajax.request({
            url: u,
            method: 'POST',
            params : data,

            success: function(response, opts) {
                const obj = Ext.decode(response.responseText);
                console.dir(obj);
            },

            failure: function(response, opts) {
                console.log('server-side failure with status code ' + response.status);
            }
        });
    }

这对数据库进行了“正确”调用,并且我看到了预期的凭据。但是我注意到,在未来的任何调用中,会话 cookie 都不会被发送存储(chrome 不会存储 cookie),并且每次发送/创建一个 new 会话 cookie。

是什么造成了这种差异?为什么 sencha/chrome 不存储 cookie?

为了完整起见,sails 中的服务器(使用 expressjs 会话存储)转到:

login: async function(req, res) {
  try {
    const user = await User.findOne({username: req.body.username});
    const sess = req.session;
    if (sess.userId === user.id) {
      res.json({succes: false, message: 'already logged in'});
      return;
    }
    if (!user) {
      res.json({success: false, message: 'Authentication failed. User not found.'});
    } else {
      // check if password matches
      const valid = await comparePromise(req.body.password, user.password);
      if(valid) {
        // if user is found and password is right
        req.session.userId = user.id;
        res.json({success: true, user: user});
      } else {
        res.forbidden(JSON.stringify({ success: false, message: 'Authentication failed. Wrong password.' }));
      }
    }
  } catch (err) {
    console.log(err);
    res.badRequest(JSON.stringify({success: false, message: err.message}));
  }
},

【问题讨论】:

  • 您的 Sencha Modern 应用程序是否与后端位于同一台服务器上? (如果是这样,为什么要使用完全限定的端点 URL?)
  • 不,这是在测试期间——它们都在我的开发电脑上运行在不同的端口上。一个是在端口 1337 通过npm start 运行的sails 服务器-另一个在端口1841 通过sencha app watch 运行。给出完全限定的url 来强调这个“点”(表单url 后面的实际代码检查前端是否是为调试或生产而构建的)。
  • 恕我直言,问题是 CORS 问题。我不知道如何解决它,但是如果您改写您的问题以强调您的请求是跨域的并添加 CORS 标签,那么有人可能会帮助您。您甚至可以尝试通过使用 ES6 fetch 或纯 XmlHttpRequest 制作示例来完全移除 Sencha。

标签: javascript session cookies extjs sails.js


【解决方案1】:

如果您的网页位于一个端口,而您的 ajax 调用是针对另一个端口的,这可以解释为什么没有保存 cookie(即使其余的请求和响应有效)。

认为不同的端口被视为不同的来源。这当然可以解释为什么邮递员成功,而从页面运行的代码却没有。我可以告诉你我是如何在我的应用程序中解决这个问题的(不是针对端口,而是针对由同一 ip 服务的不同域名)...

在 ajax 调用中,您需要将其设置为允许凭据,因为 url 的来源不同:

$.ajax({
    url: 'http://somehost.com/some/path',
    method: 'GET',
    xhrFields: { withCredentials: true },
    success: function(data) {
        // the cookie should be set here
    }
});

那么你必须在接收网址允许这个。这可能是不安全的。就我而言,我仅通过配置 routes.js 文件才允许在非常特定的 url 上进行跨源请求:

'GET /some/path': {
    controller: 'MyController',
    action: 'someAction',
    cors: {
        origin: '*',
        credentials: true
    }
},

在我的情况下,这允许 any 源使用凭据访问该路由,并获取 cookie。在您的情况下,您可能可以使用类似

cors: {
    allowOrigins: ['http://localhost:1337', 'http://localhost:1841']
    credentials: true
}

...但我不确定我的语法是否适合。有些文档是here

如果您需要对整个应用进行更通用的设置,我认为sails 有一些方法可以从 cors.js 配置文件中做到这一点,但在这样做之前您应该考虑安全性。

我认为一旦你有了 cookie,它应该包含在所有端口的所有请求中(即,我不认为包括 cookie 是特定于端口的,只是存储它们)。

祝你好运!

【讨论】:

    猜你喜欢
    • 2021-07-05
    • 1970-01-01
    • 2012-02-10
    • 2019-05-19
    • 1970-01-01
    • 2011-04-26
    • 2011-02-21
    相关资源
    最近更新 更多