node.js 服务器上的用户会话未更新
User session not updating on node.js server
我目前正在努力让用户的会话根据客户端的更新请求进行更新。这里的思路是更新成功后,立即将更新后的用户数据展示给Client。为此,我使用会话来存储数据,而不必在每次刷新时都向数据库发出获取请求。
我的问题是,每当用户更新自己时,会话仍然保留登录后检索到的先前值,尽管我将其设置为新值。所以 updateMyProfile 请求不会保存会话中的数据。这是我用我的 Authenticate 请求测试的,该请求在刷新时调用以检索 currentUser
的用户数据
/服务器
app.use(
session({
key: "someID",
secret: "someSecret", //Normally this has to be long and complex for security
resave: false,
rolling: true,
saveUninitialized: false,
cookie: { //How long will the cookie live for?
expires: 60 * 60 * 1000, //Expires after one hour
}
}));
app.patch('/updateMyProfile', verifyJWT, async(req, res) => {
const name = req.body.name;
const email = req.body.email;
const phoneNr = req.body.phoneNr;
const id = req.body.id;
var updated = "UPDATE users set name = ?, email = ?, phoneNr = ? WHERE id = ?;";
var retrieved = "SELECT * FROM users WHERE id = ?;";
db.query(updated, [name, email, phoneNr, id],
(err, result) => {
if (err) {
res.send({message: err}) //Sending error to front-end
console.log(err);
}
if (result) {
db.query(retrieved, id,
(err, resultRetrieved) => {
if (err) {
res.send({message: err}) //Sending error to front-end
console.log(err);
} else {
req.session.user = resultRetrieved; //Session is updated to contain new data!
res.send({user: resultRetrieved, message: "Update succesful!"});
console.log("User is now: " + req.session.user[0].name);
res.end();
}
})}
});
});
//通过UseEffect函数在客户端每次刷新时调用此方法
app.post('/authenticate', (req, res) => { //An endpoint for user-auth
const token = req.body.token;
const userSession = req.session.user;
jwt.verify(token, "jwtSecret", (err, decoded) => {
if (err) {
res.send({auth: false, user: "No valid token!"});
console.log('No valid token');
}
else if (userSession) { //Verified user! < ----------------->
res.send({auth: true, user: userSession});
console.log(userSession[0].name + ' is in!');
}
else { //Else if user is not verified, we return an empty object with rejected authentication
res.send({auth: false, user: 'No user session!'});
console.log('No user session');
}
})
});
这是客户关于更新请求的示例
const update = () => {
Axios.patch("http://localhost:3001/updateMyProfile", {name: name, email: email, phoneNr: phoneNr, id: id},
{headers: {"x-access-token": localStorage.getItem("token")}}
).then(
(response) => {
alert(response.data.message);
}
);
}
问题
上面的代码,虽然在混合使用 server-side sessions 和 client-side sessions (JWTs) 的方式上有点不寻常,但并不是不正确的或损坏。
本例中的问题出在 client-side,处理 cookie 的方式 - 这意味着更新似乎没有应用于 session 数据。
服务器正确设置了 session cookie,并被客户端接受,但未包含在进一步的请求中。这意味着未来的请求似乎有不正确的 session 数据,因为服务器将每个请求视为一个全新的请求,没有以前存在的 session。
这个事实被隐藏了,因为 JWT 被用来验证用户是否登录,而不是检查 server-side session.
解决方案
Axios 正被用于在 client-side 上发出请求,请求未使用适当的 cookie header 发送。
要解决此问题,每个请求都应提供 withCredentials
选项,如下所示:
Axios.patch(address, data, { withCredentials: true }).then(handleResponse);
我目前正在努力让用户的会话根据客户端的更新请求进行更新。这里的思路是更新成功后,立即将更新后的用户数据展示给Client。为此,我使用会话来存储数据,而不必在每次刷新时都向数据库发出获取请求。
我的问题是,每当用户更新自己时,会话仍然保留登录后检索到的先前值,尽管我将其设置为新值。所以 updateMyProfile 请求不会保存会话中的数据。这是我用我的 Authenticate 请求测试的,该请求在刷新时调用以检索 currentUser
的用户数据/服务器
app.use(
session({
key: "someID",
secret: "someSecret", //Normally this has to be long and complex for security
resave: false,
rolling: true,
saveUninitialized: false,
cookie: { //How long will the cookie live for?
expires: 60 * 60 * 1000, //Expires after one hour
}
}));
app.patch('/updateMyProfile', verifyJWT, async(req, res) => {
const name = req.body.name;
const email = req.body.email;
const phoneNr = req.body.phoneNr;
const id = req.body.id;
var updated = "UPDATE users set name = ?, email = ?, phoneNr = ? WHERE id = ?;";
var retrieved = "SELECT * FROM users WHERE id = ?;";
db.query(updated, [name, email, phoneNr, id],
(err, result) => {
if (err) {
res.send({message: err}) //Sending error to front-end
console.log(err);
}
if (result) {
db.query(retrieved, id,
(err, resultRetrieved) => {
if (err) {
res.send({message: err}) //Sending error to front-end
console.log(err);
} else {
req.session.user = resultRetrieved; //Session is updated to contain new data!
res.send({user: resultRetrieved, message: "Update succesful!"});
console.log("User is now: " + req.session.user[0].name);
res.end();
}
})}
});
});
//通过UseEffect函数在客户端每次刷新时调用此方法
app.post('/authenticate', (req, res) => { //An endpoint for user-auth
const token = req.body.token;
const userSession = req.session.user;
jwt.verify(token, "jwtSecret", (err, decoded) => {
if (err) {
res.send({auth: false, user: "No valid token!"});
console.log('No valid token');
}
else if (userSession) { //Verified user! < ----------------->
res.send({auth: true, user: userSession});
console.log(userSession[0].name + ' is in!');
}
else { //Else if user is not verified, we return an empty object with rejected authentication
res.send({auth: false, user: 'No user session!'});
console.log('No user session');
}
})
});
这是客户关于更新请求的示例
const update = () => {
Axios.patch("http://localhost:3001/updateMyProfile", {name: name, email: email, phoneNr: phoneNr, id: id},
{headers: {"x-access-token": localStorage.getItem("token")}}
).then(
(response) => {
alert(response.data.message);
}
);
}
问题
上面的代码,虽然在混合使用 server-side sessions 和 client-side sessions (JWTs) 的方式上有点不寻常,但并不是不正确的或损坏。
本例中的问题出在 client-side,处理 cookie 的方式 - 这意味着更新似乎没有应用于 session 数据。
服务器正确设置了 session cookie,并被客户端接受,但未包含在进一步的请求中。这意味着未来的请求似乎有不正确的 session 数据,因为服务器将每个请求视为一个全新的请求,没有以前存在的 session。 这个事实被隐藏了,因为 JWT 被用来验证用户是否登录,而不是检查 server-side session.
解决方案
Axios 正被用于在 client-side 上发出请求,请求未使用适当的 cookie header 发送。
要解决此问题,每个请求都应提供 withCredentials
选项,如下所示:
Axios.patch(address, data, { withCredentials: true }).then(handleResponse);