CORS通话后,Express Session无法持续 [英] Express Session not persisting after CORS calls

查看:77
本文介绍了CORS通话后,Express Session无法持续的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR:

无法成功执行多个API调用之间的持久会话在Backbone App和带有Express的Node.js服务器之间,Express-Session和Express-Cors.会话似乎已重新初始化/丢失每次通话后.

Can't succeed persisting session across multiple APIs call performed between a Backbone App and Node.js Server with Express, Express-Session and Express-Cors. Looks like session is reinitialized/lost after every call.

长版:

我有一个运行在 localhost:3000 上的客户端Backbone/React/Flux应用程序,在运行在 localhost:4242 上的Node.js服务器上执行以下调用:

I'm having a client Backbone/React/Flux application running on localhost:3000 performing the following call on a Node.js server running on localhost:4242:

Http呼叫

POST http://localhost:4242/api/session

 RESPONSE HEADERS
 Content-Type application/json; charset=utf-8
 Set-Cookie connect.sid=s%3AFeNYY5GQGvkyRvOym7DhysprePaQr7xP.BrxOPP56k9pDpxQPvwjDFaxkEYoHU%2FAEtNUIXGltqjI; Domain=http://localhost:3000; Path=/
 Vary Origin
 X-Powered-By Express
 access-control-allow-credentials   true
 access-control-allow-orign http://localhost:3000
 [...]

 REQUEST HEADERS
 Accept application/json, text/javascript, */*; q=0.01
 Content-Type application/json; charset=utf-8
 Cookie connect.sid=s%3AjP4iADZvRnDHbJcCE8H81Zy6TIehj9BJ.eDOTw44GcHqq8i2dslBGd43tXMQ22ENl31fRizdC8iA
 Host localhost:4242
 Origin http://localhost:3000
 Referer http://localhost:3000/login
 [...]

获取 http://localhost:4242/api/users

 RESPONSE HEADERS
 Content-Type application/json; charset=utf-8
 Set-Cookie connect.sid=s%3ARxf91_vLMBqzB6xN-0QFIIk_-SyBP9_8.F1Mr%2BVSkYNJ6MqnzO%2BsxxfwXRinIX6th80SoukG1QBM;Domain=http://localhost:3000; Path=/
 Vary Origin
 X-Powered-By Express
 access-control-allow-credentials   true
 access-control-allow-orign http://localhost:3000
 [...]

 REQUEST HEADERS
 Accept application/json, text/javascript, */*; q=0.01
 Content-Type application/json; charset=utf-8
 Cookie connect.sid=s%3AjP4iADZvRnDHbJcCE8H81Zy6TIehj9BJ.eDOTw44GcHqq8i2dslBGd43tXMQ22ENl31fRizdC8iA
 Host localhost:4242
 Origin http://localhost:3000
 Referer http://localhost:3000/login
 [...]

基本上,第一个调用 POST/api/session 是登录用户并尝试在会话中存储API令牌.第一个调用 GET/api/users 在第一个调用成功后立即触发,并检索用户信息.

Basically the first call POST /api/session is logging-in the user and attempting to store an API token in the session. Second call GET /api/users is triggered right after the first one succeed, and retrieving user information.

骨干方法

这是用于登录的Session模型上的Backbone方法:

Here's my Backbone method on the Session model for logging-in :

  login: (options) ->
    @set {user: options.user, password: options.password}
    @save ['user', 'password'],
      success: (data) =>
        @set({authenticated: true, accessToken: data.accessToken, password: null})
        options.success(data) # trigger the second call here
      error: (error) =>
        options.error(error)

然后在我的UserStore中对/api/users的调用

And the call to /api/users in my UserStore

users: (options) ->
  @users.fetch
    success: (users) =>
      @users = users
      options.success(users)

使用这些不同的选项(我已经在Backbone.Collection/Backbone.Model中覆盖了Backbone.sync):

Using those different options (I've overridden Backbone.sync in Backbone.Collection/Backbone.Model):

class UsersCollection extends Backbone.Collection

  url: '/api/users'
  model: UserModel

  sync: (method, model, options) ->
    options ?= {}
    options.url ?= @url
    options.dataType ?= 'json'
    options.contentType ?= "application/json; charset=utf-8"
    options.crossDomain ?= true
    options.xhrFields ?= {"withCredentials": true}
    super(method, model, options)

(简化版:使用BaseCollection和BaseModel的Model和Collection都是相同的,在这里我覆盖了sync()方法).

(Simplified version: same thing for both Models and Collection, using BaseCollection and BaseModel, where I am overridding the sync() method).

因此 Backbone.sync(方法,模型,选项)中的 Console.log(选项)正在返回:

{"url":"http://localhost:4242/api/session","dataType":"json","contentType":"application/json; charset=utf-8","crossDomain":true,"validate":true,"parse":true,"xhrFields":{"withCredentials":true}} 

Node.js设置和方法

这是我的Node.js路由器设置Express:

Here's my Node.js router setting-up Express :

BodyParser = require 'body-parser'
Session = require 'express-session'
Cors = require 'cors'

class Router

  constructor: (express) ->
    @express = express
    @express.use BodyParser.json()
    @express.use Cors(@corsConfig())
    @express.use Session(@sessionConfig())
    # Express routes are set here
    # @express.post '/api/session', (request, response) => [...]
    # @express.get '/api/users', (request, response) => [...]

  corsConfig: ->
    origin: 'http://localhost:3000'
    credentials: true

  sessionConfig: ->
    secret: 'whatever'
    cookie:
      secure: false
      httpOnly: false
      domain: 'http://localhost:3000'

这是我的Node.js方法,用于处理 POST/api/session

Here's my Node.js method handling POST /api/session

  login: (request, response) ->
    session = request.session
    console.log JSON.stringify(session)
    console.log request.sessionID
    console.log '---------------------------------------------'
    if session.accessToken
      console.log 'session with token!'
      response.json {accessToken: session.accessToken}
    else
      console.log 'performing credentialAuthentication'
      user = request.body.user
      password = request.body.password
      @whatever.authentication
        user: user
        password: password
        success: (accessToken) ->
          request.session.accessToken = accessToken
          console.log JSON.stringify(session)
          console.log request.sessionID
          console.log '---------------------------------------------!!!'
          response.json {accessToken: accessToken}
          # also tried with response.send()

一个处理 GET/api/users

  @express.get '/api/users', (request, response) =>
    console.log JSON.stringify(request.session)
    console.log request.sessionID
    console.log '---------------------------------------------'
    [...]

Node.js日志

这是日志:

  express:router dispatching OPTIONS /api/session
  express:router dispatching POST /api/session
{"cookie":{"originalMaxAge":null,"expires":null,"secure":false,"httpOnly":false,"path":"/"}}
zse18d2zrNRdEXPjFHF0gm3NkONb-_5V
---------------------------------------------
performing credentialAuthentication
{"cookie":{"originalMaxAge":null,"expires":null,"secure":false,"httpOnly":false,"path":"/"},
"accessToken":"ebab5010f9ece5ea984e4b73f9a46ef3"}
zse18d2zrNRdEXPjFHF0gm3NkONb-_5V
---------------------------------------------!!!
  express:router dispatching GET /api/users
{"cookie":{"originalMaxAge":null,"expires":null,"secure":false,"httpOnly":false,"path":"/"}}
g8YXQEpt_rnWSGdh1nCKMndiI8Lt2UDq
---------------------------------------------

您可以看到CORS请求正在正常执行,我正在正确获取令牌,然后尝试将其存储在会话中.

As you can see the CORS request is performing normally, I am properly getting my token and then attempting to store it within the session.

但是,在第二个呼叫中该会话没有持久化,并且我无法访问我在第一个呼叫中实际设置的变量(accessToken).

查看两个调用的日志和HTTP标头,看起来每次会话都被重新初始化,因为会话ID不断变化,每个请求都有-并且每次都发送一个Set-Request标头(据我了解,情况并非如此).

Looking at the log and at the HTTP Headers of the two call, it looks like the session is reinitialized each time, as the session ID is changing and each request - and there is a Set-Request header sent every time (which shouldn't be the case, as far as I understand).

我怀疑此行为是由于CORS级别上的某些配置不一致或缺少配置所致,或者是由于为会话设置的 path ( Express.use(path,middleware)>和 Cookie({path:'/'})).但是,尽管尝试了不同的配置,设置和标题,但我确实无法使它正常工作.

I suspect this behavior is caused by some incoherent or missing configuration at the CORS level, or due to the path set for Sessions (Express.use(path, middleware), and Cookie({path: '/'})). However, despite many attempt with different configuration, setup and headers, I really can't make it work.

任何能启发我这种行为的人,我所缺少的都是非常受欢迎的:)
谢谢!

Anyone able to enlighten me on this behavior and what I am missing is very welcome :)
Thank you!

PS:我对非CoffeeScript开发人员表示歉意;)

PS: My apologies to the non-CoffeeScript developers ;)

推荐答案

以下是答案(简单的答案):我对会话中间件的配置错误; cookie.domain 选项引起了该问题.这是正确的配置:

Here's the answer (simple one): I had misconfigured my Session middleware; The cookie.domain options was causing the problem. Here's the proper configuration :

sessionConfig: ->
  secret: 'whatever'
  cookie:
    secure: false
    httpOnly: false

快速/会话中间件不再需要/不存在此选项;不知道为什么我最初使用它,可能来自过时的参考资料(用于表达/cookie解析器或表达/cors).

This option isn't required/existing (anymore?) with the express/session middleware; Not sure why I originally used it, probably something from an outdated reference (to express/cookie-parser or express/cors).

这篇关于CORS通话后,Express Session无法持续的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆