如何正确存储我的 JWT 令牌并在 MERN 应用程序中返回数据

如何解决如何正确存储我的 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,因为您只是在服务器端生成它。流程是这样的:

  1. 注册:用户提供用户名和密码。您将用户保存在数据库中,并为密码保存一个哈希值。
  2. 登录时,用户提供用户名和密码。如果它们正确,则创建一个 JWT 并将其返回给客户端应用程序。在 JWT 中,您将对 username/user_id 进行编码。
  3. 客户端需要将该 JWT 存储在某处,然后在以下请求中发送它(通常作为标头)。
  4. 在服务器上,您有一个中间件,可以解析该标头、解码 JWT 并根据用户名/user_id 或您在其中编码的任何内容识别用户。

客户端不应解码 JWT 并从那里提取用户名等信息。它应该向后端发出 API 请求,要求提供用户信息。

这里有很多事情需要考虑。仅举几例:

  • 您如何以安全的方式将 JWT 存储在客户端上?
  • 在客户端应用中,您如何防止未经身份验证的用户访问某些私有路由?
  • JWT 到期后你会做什么?
  • 您如何处理 CORS?
  • 是否存在漏洞?

我强烈推荐这个free course,它会教你很多关于如何实现这些东西的知识。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res