在 Heroku 上托管时,快速会话不会保存护照用户 ID
Express session does not save the passport user id when hosting on Heroku
我正在开发一个网站,用户可以在其中登录并搜索不同的 TfL 数据,我将在后端向 API 发送请求。我在 netlify 上托管我的前端,在 Heroku 上托管我的后端。我的问题是,当用户按下登录按钮时,会话数据会显示他们的用户 ID。但是,当用户被重定向到主页时,我再次打印出会话数据,但是会话中没有用户 ID。
需要注意的是,当用户通过 ajax 按下登录时,我会将用户重定向到另一个域,然后后端对他们进行身份验证,如果成功,我会将状态响应 200 发送回 ajax 回调,然后我用户 window.location.href 将用户推进到主页。
我已经尝试过各种方法,例如 cors、将凭据设置为 true、使用 mongostore,几乎所有你能想到的方法。
我的后端快递代码片段
function loggedIn(req, res, next) {
console.log(req.session);
if (req.user) {
next();
} else {
res.sendStatus('501');
}
}
app.use(cookieParser());
// Express Session
app.use(session({
secret: "secret",
cookie: {
secure: true,
},
saveUninitialized: true,
resave: true,
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.getUserFromId(id, (err, user) => {
done(err, user);
});
});
app.post('/login', urlencodedParser, passport.authenticate('local', {failureRedirect: '/login-error', failureFlash: true}), (req, res) => {
req.session.save( err => {
res.send(req.user);
console.log(req.session);
});
});
app.get('/search', loggedIn, urlencodedParser, (req, res) => {
Search.find({user: req.user._id}, (err, data) => {
if(err) throw err;
res.send({searches: data});
});
});
用户加载主页后立即进行的AJAX调用
$.ajax({
//The type of the request is a GET request.
type: 'GET',
//We're doing a GET request to that route.
url: 'https://tfldatavis.herokuapp.com/search',
data: '',
xhrFields: {
withCredentials: true
},
//On success of the request, some data will be sent back and this function wil be fired.
success: data => {
for(let i = data.length-1; i >= 0; i--) {
$('#search-history').append('<span style="color: #2c313a">' + data.searches[i].search + '</span>');
}
},
error: (err, data) => {
if (data.status === 501) {
window.location.href = 'https://www.emreedogan.com/login';
}
}
});
当用户按下登录按钮时进行的 AJAX 调用
$.ajax({
//The type of the request is a POST request.
type: 'POST',
//We're doing a POST request to that route.
url: 'https://tfldatavis.herokuapp.com/login',
//Pass along the data inside 'searchQuery' along with the request.
data: user,
xhrFields: {
withCredentials: true
},
//On success of the request, some data will be sent back and this function wil be fired.
success: data => { console.log(data); window.location.href = 'https://www.emreedogan.com/index'; },
error: (req, status, err) => {
const message = req.responseJSON.error[0];
$('#error-message').text(message);
if (message.indexOf("Email") >= 0) {
$('input[type="email"]').focus();
} else if (message.indexOf("password") >= 0) {
$('input[type="password"]').focus();
}
}
});
当用户加载主页并向 /search 发出 GET 请求时,会话数据应包括护照:{user: -whatever-}。但是,它没有,就像它根本没有保存会话一样。
这是 Heroku 日志的输出:
第一个会话信息输出是在用户被定向到主页之前。第二个会话信息输出是在用户被定向到主页并向 /search 发出 GET 请求之后。
更新:我通过在 chrome 中清除浏览器 cookie 解决了我的问题。如果其他人遇到此问题,我建议您也尝试一下!此外,如果您使用 AJAX 向后端发出请求,请确保将其包含在 AJAX 代码中:
xhrFields: {
withCredentials: true
}
另外,如果您要发出跨域请求,请确保您的后端可以接受这些请求:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next();
});
我希望这对遇到此问题的任何人有所帮助!如果没有,请不要放弃!
我正在开发一个网站,用户可以在其中登录并搜索不同的 TfL 数据,我将在后端向 API 发送请求。我在 netlify 上托管我的前端,在 Heroku 上托管我的后端。我的问题是,当用户按下登录按钮时,会话数据会显示他们的用户 ID。但是,当用户被重定向到主页时,我再次打印出会话数据,但是会话中没有用户 ID。
需要注意的是,当用户通过 ajax 按下登录时,我会将用户重定向到另一个域,然后后端对他们进行身份验证,如果成功,我会将状态响应 200 发送回 ajax 回调,然后我用户 window.location.href 将用户推进到主页。
我已经尝试过各种方法,例如 cors、将凭据设置为 true、使用 mongostore,几乎所有你能想到的方法。
我的后端快递代码片段
function loggedIn(req, res, next) {
console.log(req.session);
if (req.user) {
next();
} else {
res.sendStatus('501');
}
}
app.use(cookieParser());
// Express Session
app.use(session({
secret: "secret",
cookie: {
secure: true,
},
saveUninitialized: true,
resave: true,
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.getUserFromId(id, (err, user) => {
done(err, user);
});
});
app.post('/login', urlencodedParser, passport.authenticate('local', {failureRedirect: '/login-error', failureFlash: true}), (req, res) => {
req.session.save( err => {
res.send(req.user);
console.log(req.session);
});
});
app.get('/search', loggedIn, urlencodedParser, (req, res) => {
Search.find({user: req.user._id}, (err, data) => {
if(err) throw err;
res.send({searches: data});
});
});
用户加载主页后立即进行的AJAX调用
$.ajax({
//The type of the request is a GET request.
type: 'GET',
//We're doing a GET request to that route.
url: 'https://tfldatavis.herokuapp.com/search',
data: '',
xhrFields: {
withCredentials: true
},
//On success of the request, some data will be sent back and this function wil be fired.
success: data => {
for(let i = data.length-1; i >= 0; i--) {
$('#search-history').append('<span style="color: #2c313a">' + data.searches[i].search + '</span>');
}
},
error: (err, data) => {
if (data.status === 501) {
window.location.href = 'https://www.emreedogan.com/login';
}
}
});
当用户按下登录按钮时进行的 AJAX 调用
$.ajax({
//The type of the request is a POST request.
type: 'POST',
//We're doing a POST request to that route.
url: 'https://tfldatavis.herokuapp.com/login',
//Pass along the data inside 'searchQuery' along with the request.
data: user,
xhrFields: {
withCredentials: true
},
//On success of the request, some data will be sent back and this function wil be fired.
success: data => { console.log(data); window.location.href = 'https://www.emreedogan.com/index'; },
error: (req, status, err) => {
const message = req.responseJSON.error[0];
$('#error-message').text(message);
if (message.indexOf("Email") >= 0) {
$('input[type="email"]').focus();
} else if (message.indexOf("password") >= 0) {
$('input[type="password"]').focus();
}
}
});
当用户加载主页并向 /search 发出 GET 请求时,会话数据应包括护照:{user: -whatever-}。但是,它没有,就像它根本没有保存会话一样。
这是 Heroku 日志的输出:
第一个会话信息输出是在用户被定向到主页之前。第二个会话信息输出是在用户被定向到主页并向 /search 发出 GET 请求之后。
更新:我通过在 chrome 中清除浏览器 cookie 解决了我的问题。如果其他人遇到此问题,我建议您也尝试一下!此外,如果您使用 AJAX 向后端发出请求,请确保将其包含在 AJAX 代码中:
xhrFields: {
withCredentials: true
}
另外,如果您要发出跨域请求,请确保您的后端可以接受这些请求:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next();
});
我希望这对遇到此问题的任何人有所帮助!如果没有,请不要放弃!