以前没有注意到这一点,因为对于客户端-服务器通信,不需要通过 XHR 进行身份验证(到目前为止)。在实现一些集成测试时,我正在为应用程序的真实实例创建真正的请求 node-xmlhttprequest。用户在第一个请求中进行身份验证,理论上用户的唯一标识符和其他一些相关信息存储在会话中(正如我所说,这对于不需要通过 XHR 确认身份的真实客户来说很好用)。出于某种原因,即使使用完全相同的会话 ID 触发后续请求,我也无法在后续请求中检索会话,因此无法看到用户已通过身份验证,这会导致测试失败,其中没有发生预期的行为,
我见过几个看起来像这样的问题,但其中似乎不存在“相同的会话 ID”的东西。
我是否需要手动将 Set-Cookie 标头添加到所有 XHR 请求?太可怕了,一定有更好的方法!
所以人们喜欢源代码,这里有一些来自测试,触发这些请求:
// Ensure logged in before sending request, to verify that authorized
// users encounter the expected behaviour.
jQuery.post(domain+'/login', {email:'test@express.app', password:'12345678'},
function(data,x,y){
data.should.equal("true")
jQuery.ajax({url:domain+'/event', type:"POST",
name: "TestEvent", location: "TestVille",
startDate: new Date('2013-09-01'), startTime: '6:45 pm',
description: "Test Event #1", success: state.success,
error: state.error, completed: state.completed
})
})
登录发生,用户 ID 被写入会话(`req.logIn() 应该这样做,并且它不报告任何失败),用户 ID 的序列化不报告任何失败,我非常困惑为什么后续使用相同会话 ID 的请求无法找到序列化的用户 ID。
我通常不参与 Web 开发,所以这对某些人来说可能很明显,但我整天都在寻找答案,但根本找不到答案。我将不胜感激任何指针,并且很乐意提供尽可能多的代码来说明问题所在。
一些可能相关的附加代码点:
用户 ID 的序列化/反序列化(目前以最简单的方式实现——这是在初始化护照和 passpot.session() 之后的中间件初始化的早期阶段。这对于非 XHR 请求非常有效)
// Serialize user for passport session-store
// Currently only serializing 'user_id'
passport.serializeUser(function(user, done) {
done(null, user._id)
})
// Deserialize user from session-store to provide
// access to the User instance
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user)
})
})
通过本地策略对用户进行身份验证:
passport.use(new LocalStrategy({
usernameField: "email", passwordField: "password",
passReqToCallback: true, failureFlash: true
},
function(req, email, password, done) {
User.findByEmail(email, function(err, user) {
if(user) {
if(err) console.log(err)
if(user instanceof UserLocal) {
user.verifyPassword(password, function(err, match) {
if(err) console.log(err)
if(!match) {
return done(err, false,
"Username or password is incorrect.")
}
return done(null, user)
})
} else {
var msg = "Account registered under " + user.providerName()
+ ", please login using " + user.providerName()
return done(err, false, msg)
}
} else {
return done(err, false, "Username or password is incorrect.")
}
})
})
最后是首先写入会话的请求:
function loginHelper(req, res, next) {
passport.authenticate('local', {
failureFlash:true,
failureRedirect: false,
successRedirect: false
},
function(err, user, info) {
req.logIn(user, function(err) {
if(!err) err = {}
if(req.xhr) {
console.log(req.session)
res.status(200).end(err.message || "true")
} else {
if(err.message) req.flash('error', err.message)
else res.redirect('/')
}
})
})(req, res, next)
}
我知道有一些奇怪的事情,比如无论登录状态如何都发送状态为 200,但我可以确认序列化的用户 ID 在初始登录 XHR 请求中写入会话,并且在后续 XHR 请求中没有反序列化。
正如我相信我提到的那样,我在这方面相对缺乏经验,并且可以非常使用助推器。任何帮助将不胜感激,在此先感谢。