我正在开发一个网站,用户可以在该网站上登录并搜索不同的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请求时,会话数据应包括passport:{user:-whatever-}。但是,它没有,它就像它根本不保存会话。
这是Heroku日志的输出:
第一个会话信息输出在用户被定向到主页面之前。第二个会话信息输出是在用户被定向到主页面并且进行/搜索的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();
});
我希望这有助于任何遇到此问题的人!如果没有,不要放弃!