如何解决如何正确存储我的 JWT 令牌并在 MERN 应用程序中返回数据
我正在创建一个 MERN 应用程序,因为我正在学习如何使用 React 创建一个博客/社交媒体(如网站)。我已经设置了路由和 jsx,以便通过 axios 请求显示帖子并从我的 MongoDB 集群中提取数据。
这一切都很完美,但我现在正在努力寻找一种正确的方法来处理用户身份验证并将数据显示回我的 MERN 应用程序。 我当前注册用户的代码采用他们的姓名、电子邮件和密码;使用 bcrpyt 对密码进行散列/加盐以确保安全。
注册码
exports.register = (req,res,next) => {
let {
name,email,password,password_confirmation
} = req.body;
User.findOne({
email: email
})
.then(user => {
if (user) {
return res.status(422).json({
errors: [{
user: "email already exists"
}]
});
} else {
const user = new User({
name: name,email: email,password: password,});
bcrypt.genSalt(10,function (err,salt) {
bcrypt.hash(password,salt,hash) {
if (err) throw err;
user.password = hash;
user.save()
.then(response => {
res.status(200).json({
success: true,result: response
})
})
.catch(err => {
res.status(500).json({
errors: [{
error: err
}]
});
});
});
});
}
}).catch(err => {
res.status(500).json({
errors: [{
error: 'Something went wrong'
}]
});
})
}
然后我的登录函数使用 bcrypt.compare 以确保密码类型与存储在数据库中的散列密码匹配。如果成功,我的代码将调用我创建的名为 createJWT 的函数,该函数的有效负载包含电子邮件、用户 ID 和到期前令牌的持续时间。
const jwt = require("jsonwebtoken");
exports.createJWT = (email,userId,duration) => {
const payload = {
email,duration
};
return jwt.sign(payload,process.env.TOKEN_SECRET,{
expiresIn: duration,});
};
登录代码
exports.login = (req,res) => {
let {
email,password
} = req.body;
User.findOne({
email: email
}).then(user => {
if (!user) {
return res.status(404).json({
errors: [{
user: "not found"
}],});
} else {
bcrypt.compare(password,user.password).then(isMatch => {
if (!isMatch) {
return res.status(400).json({
errors: [{
password: "incorrect"
}]
});
}
let access_token = createJWT(
user.email,user._id,3600
);
jwt.verify(access_token,(err,decoded) => {
if (err) {
res.status(500).json({
errors: err
});
}
if (decoded) {
return res.status(200).json({
success: true,token: access_token,message: user
});
}
});
}).catch(err => {
res.status(500).json({
errors: err
});
});
}
}).catch(err => {
res.status(500).json({
errors: err
});
});
}
如果登录功能成功,如果令牌与存储在我的 env 文件中的 TOKEN_SECRET 匹配,代码将解码 JWT 代码。
这一切都很好,但我在下一步要去哪里的时候被卡住了。我创建了一个中间件,我可以成功地将其实施到我的路由中,以便在用户未经授权时停止加载。
//Auth middleware
const jwt = require('jsonwebtoken');
module.exports = (req,next) => {
try {
const token = req.header('x-auth-token');
jwt.verify(token,process.env.TOKEN_SECRET);
next();
} catch (error) {
res.status(401).json({
message: "Token not authorized!"
})
}
};
const express = require('express');
const router = express.Router();
const multer = require("multer");
const authorize = require('../middleware/auth');
const {
getPosts,createPost,findPostById,updatePost,deletePost
} = require('../controllers/posts');
const storage = multer.diskStorage({
destination: (req,file,callback) => {
callback(null,'./client/public/uploads');
},filename: (req,file.originalname);
}
});
const upload = multer({
storage: storage
});
router.get('/',authorize,getPosts);
router.post('/add',upload.single("postImage"),createPost);
router.get('/:id',findPostById);
router.put('/update/:id',updatePost);
router.delete('/:id',deletePost);
module.exports = router;
从这一点来看,如果用户成功登录并拥有 JWT 令牌,那么让用户登录并访问帖子(包含我的授权中间件)的最佳方式是什么。我还想知道如何实现诸如从解码的令牌中提取用户名并在导航栏中显示(例如)只要他们登录/会话持续存在的东西。
这里的任何帮助将不胜感激,谢谢大家!
解决方法
let access_token = createJWT(
user.email,user._id,3600
);
jwt.verify(access_token,process.env.TOKEN_SECRET,(err,decoded) => {
if (err) {
res.status(500).json({
errors: err
});
}
if (decoded) {
return res.status(200).json({
success: true,token: access_token,message: user
});
}
});
这里没有必要验证 JWT,因为您只是在服务器端生成它。流程是这样的:
- 注册:用户提供用户名和密码。您将用户保存在数据库中,并为密码保存一个哈希值。
- 登录时,用户提供用户名和密码。如果它们正确,则创建一个 JWT 并将其返回给客户端应用程序。在 JWT 中,您将对 username/user_id 进行编码。
- 客户端需要将该 JWT 存储在某处,然后在以下请求中发送它(通常作为标头)。
- 在服务器上,您有一个中间件,可以解析该标头、解码 JWT 并根据用户名/user_id 或您在其中编码的任何内容识别用户。
客户端不应解码 JWT 并从那里提取用户名等信息。它应该向后端发出 API 请求,要求提供用户信息。
这里有很多事情需要考虑。仅举几例:
- 您如何以安全的方式将 JWT 存储在客户端上?
- 在客户端应用中,您如何防止未经身份验证的用户访问某些私有路由?
- JWT 到期后你会做什么?
- 您如何处理 CORS?
- 是否存在漏洞?
我强烈推荐这个free course,它会教你很多关于如何实现这些东西的知识。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。