[英]Express Session not persisting after CORS calls
TL;DR: TL; DR:
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. 无法成功在Backbone应用程序和具有Express,Express-Session和Express-Cors的Node.js服务器之间执行的多个API调用之间持久保存会话。 Looks like session is reinitialized/lost after every call. 每次通话后会话似乎都重新初始化/丢失了。
Long version: 长版:
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
: 我有一个运行在localhost:3000
上的客户端Backbone / React / Flux应用程序,在运行在localhost:4242
上的Node.js服务器上执行以下调用:
Http calls Http调用
POST http://localhost:4242/api/session 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
[...]
GET http://localhost:4242/api/users GET 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
[...]
Basically the first call POST /api/session
is logging-in the user and attempting to store an API token in the session. 基本上,第一次调用POST /api/session
是登录用户并尝试在会话中存储API令牌。 Second call GET /api/users
is triggered right after the first one succeed, and retrieving user information. 第一个调用GET /api/users
在第一个调用成功之后立即触发,并检索用户信息。
Backbone method 骨干法
Here's my Backbone method on the Session model for logging-in : 这是我在Session模型上进行登录的Backbone方法:
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)
And the call to /api/users in my UserStore 以及对我的UserStore中的/ api / users的调用
users: (options) ->
@users.fetch
success: (users) =>
@users = users
options.success(users)
Using those different options (I've overridden Backbone.sync in Backbone.Collection/Backbone.Model): 使用这些不同的选项(我在Backbone.Collection / Backbone.Model中覆盖了Backbone.sync):
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)
(Simplified version: same thing for both Models and Collection, using BaseCollection and BaseModel, where I am overridding the sync() method). (简化版:使用BaseCollection和BaseModel对Models和Collection都使用相同的方法,在这里我覆盖了sync()方法)。
So that Console.log(options)
in Backbone.sync(method, model, options)
is returning : 因此Backbone.sync(method, model, options)
中的Console.log(options)
Backbone.sync(method, model, options)
正在返回:
{"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 setup and methods Node.js设置和方法
Here's my Node.js router setting-up Express : 这是我的Node.js路由器设置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'
Here's my Node.js method handling POST /api/session
这是我的Node.js方法,处理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()
And the one handling GET /api/users
和一个处理GET /api/users
@express.get '/api/users', (request, response) =>
console.log JSON.stringify(request.session)
console.log request.sessionID
console.log '---------------------------------------------'
[...]
Node.js Log Node.js日志
Here's the log: 这是日志:
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
---------------------------------------------
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. 如您所见,CORS请求正在正常执行,我正在正确获取令牌,然后尝试将其存储在会话中。
However in the second call the session isn't persisted and I can't access the variable (accessToken) that I am actually setting in my first call. 但是,在第二个呼叫中,会话不会保留,并且我无法访问我在第一个呼叫中实际设置的变量(accessToken)。
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). 查看两个调用的日志和HTTP标头,看起来每次会话都被重新初始化,因为会话ID不断变化,每个请求都有-并且每次发送一个Set-Request标头(这不应该据我了解,确实如此)。
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: '/'})
). 我怀疑此行为是由于CORS级别上的某些配置不一致或缺少配置所致,或者是由于为会话设置的path
( Express.use(path, middleware)
和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: My apologies to the non-CoffeeScript developers ;) PS:我对非CoffeeScript开发人员表示歉意;)
Here's the answer (simple one): I had misconfigured my Session middleware; 答案是一个(简单的答案):我错误地配置了会话中间件。 The cookie.domain
options was causing the problem. cookie.domain
选项导致了问题。 Here's the proper configuration : 这是正确的配置:
sessionConfig: ->
secret: 'whatever'
cookie:
secure: false
httpOnly: false
This option isn't required/existing (anymore?) with the express/session middleware; express / session中间件不再需要/不存在此选项; Not sure why I originally used it, probably something from an outdated reference (to express/cookie-parser or express/cors). 不知道为什么我最初使用它,可能来自过时的参考资料(表达/ cookie解析器或表达/心律)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.