我想使用我的登录数据(用户名、ID)并将它们存储在其他表中,以便访问存储在这些表中的其他数据。我对服务器使用Node.js和express,对会话使用express-session模块。以下是app.js和会话中间件及其默认选项
import session from 'express-session';
app.use(session({
name:'test',
secret: "thisismysecrctekeyfhrgfgrfrty84fwir767",
saveUninitialized: true,
resave: false
}));
//some other stuff
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use((_, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
app.use((req,res,next) => {
console.log('req.session',req.session);
next();
});
在此之后,我使用路由器为我所有的路线,这里是登录路线,我保存我的用户名到会话中
router.post('/login', (req, res, next) => {
// checks if email exists
User.findOne({ where : { //
name: req.body.name, //
}})
.then(dbUser => {
if (!dbUser) {
return res.status(404).json({message: "user not found"});
} else {
// password hash
bcrypt.compare(req.body.password, dbUser.password, (err, compareRes) => {
if (err) { // error while comparing
res.status(502).json({message: "error while checking user password"});
} else if (compareRes) {
// password match
const token = jwt.sign({ name: req.body.name }, 'secret', { expiresIn: '1h' });
const sessName= req.body.name;
req.session.name=sessName;
res.status(200).json({message: "user logged in", "token": token});
} else { // password doesnt match
res.status(401).json({message: "invalid credentials"});
};
});
};
})
.catch(err => {
console.log('error', err);
});
});
用户输入登录信息后,将从登录路径转到身份验证路径
router.get('/private', (req, res, next) => {
const authHeader = req.get("Authorization");
if (!authHeader) {
return res.status(401).json({ message: 'not authenticated' });
};
const token = authHeader.split(' ')[1];
let decodedToken;
try {
decodedToken = jwt.verify(token, 'secret');
} catch (err) {
return res.status(500).json({ message: err.message || 'could not decode the token' });
};
if (!decodedToken) {
res.status(401).json({ message: 'unauthorized' });
} else {
res.status(200).json({ message: `here is your resource ${req.session.name}` });
};
});
如果我控制台记录会话,它会显示终端上的用户名,对于其他路由,当我将一些数据存储到会话上并从其他路由访问它时,它工作正常,但当我从登录路由存储用户名时,当我尝试访问它时,它不会显示。
router.get('/session', (req,res,next)=>{
if (req.session.name) {
res.json({name: req.session.name})
} else {
res.json({name: null});
}
})
我是Node.js的新手,所以如果有人能回答这个问题会很有帮助。
之后
const sessName= req.body.name;
req.session.name=sessName;
这个名字从登录路径保存在会话中,但是当我从其他路径访问它时,它显示了一个空值。2另外,当我重新启动服务器后,会话结束和用户名消失是正常的吗?
1条答案
按热度按时间dy1byipe1#
由于
/login
和/private
看起来都像是由代码生成的,所以问题可能是由于代码没有捕获会话cookie、保留它并确保它与代表同一用户的所有后续请求一起发送。会话cookie是快速会话工作的关键。在第一次与客户端参与度时,快速会话中间件发现没有会话cookie附加到这个请求上。它创建一个新的会话cookie,其中包含一个加密的唯一密钥,将该密钥添加到内部会话存储中,并将该cookie与http响应一起返回。
要使会话正常工作,接收该cookie的客户机必须保留该cookie,并将其与来自该客户机的所有未来http请求一起发送(直到它过期)。由于这些对
/login
和/private
的HTTP请求是通过编程进行的,您的代码必须正确设置以保留和发送此cookie。这将取决于你使用什么http库来发出这些http请求,你如何确切地去保留和重新发送会话cookie。如果这些请求是由运行在浏览器中的Javascript在网页中生成的,那么浏览器将为您保留Cookie,您只需要对http请求进行适当的设置,以确保Cookie被发送。如果您正在进行跨源请求,那么事情会变得有点复杂。
如果这些cookie是由你自己的代码在你自己的应用程序中生成的,那么包含cookie的具体步骤将取决于你使用的http库,许多http库都有一个通常被称为cookie jar的东西,它可以与给定的请求/响应相关联,以帮助维护和发送cookie。
现在你已经展示了你的客户端代码,代码使用
fetch()
来进行这些调用,这就是你的客户端正在使用的http请求库。由于这可能是一个跨源请求,为了确保cookie随
fetch()
发出的请求一起发送,您可以添加credentials: "include"
选项,如下所示:如果
fetch()
不发送凭据(包括cookie),那么您的会话cookie将不会被发送,您的服务器将认为它必须在每个新请求上创建一个新会话,这样您的会话将永远不会从一个请求到下一个请求被维护。