Express的使用笔记9 使用bcrypt算法给用户密码加密

先了解一下bcrypt算法,一种基于Blowfish密码学算法的密码散列函数,用于在密码存储时抵抗暴力破解攻击,通过在散列过程中加salt来提高安全性,salt是个随机生成的数据串,与密码一起被散列,使得即使两个相同的密码也会产生不同的散列值。bcrypt算法允许开发者指定工作因子(成本因子),决定散列计算的复杂度,随之硬件性能的提升,可以适当增加工作因子以保持密码的安全性。

bcrypt 算法的以下特点使其成为 Web 应用密码存储的理想选择:
加盐散列:每个密码都会有一个唯一的盐,这大大增加了破解的难度。
工作因子:可以根据需要调整散列的复杂度。
慢速散列:bcrypt 故意设计为计算密集型,以减缓暴力破解尝试。
自适应性:随着计算能力的提高,可以增加工作因子来保持密码散列的安全性。

下面开始在express中加入bcrypt。
1)npm install bcrypt
2) 在对应的文件中添加逻辑

model/user.js 中加入加密后存储的配置逻辑

const mongoose = require("mongoose");
const baseModel = require("./base-model");
const bcrypt = require("bcrypt"); //引入bcrypt 哈希处理后存储密码
const userSchema = new mongoose.Schema({
  ...baseModel,
  username: {
    type: String,
    required: true,
  },
  password: {
    type: String,
    required: true,
    set(val) {
      if (!val) return val; // 如果没有提供密码,则直接返回,不做处理
      const hashedPassword = bcrypt.hashSync(val, 10); // 对密码进行哈希处理
      return hashedPassword; // 返回哈希后的密码
    }
  },
  email: {
    type: String,
    required: true,
  },
  bio: {
    type: String,
    defualt: null,
  },
  image: {
    type: String,
    defualt: null,
  },
});

module.exports = userSchema;

在router/user.js的登录api中加入解密逻辑

const express = require("express");
const router = express.Router();
router.use(express.json());
const { body, validationResult } = require("express-validator");
const userCtrl = require("../controller/user");
const { User } = require("../model");
const bcrypt = require("bcrypt"); //引入bcrypt 哈希处理后存储密码
// 用户登录
router.post("/users/login", userCtrl.login);
// 用户注册
router.post(
  "/users",
  [
    body("user.username")
      .notEmpty()
      .withMessage("用户名不能为空")
      .bail()
      .custom(async (username) => {
        const name = await User.findOne({ username });
        if (name) {
          return Promise.reject("用户名已存在");
        }
      }),
    body("user.email")
      .notEmpty()
      .withMessage("邮箱不能为空")
      .isEmail()
      .withMessage("邮箱的格式不准确")
      .bail()
      .custom(async (email) => {
        const user = await User.findOne({ email });
        if (user) {
          return Promise.reject("邮箱已存在");
        }
      }),
  ],
  (req, res, next) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array()[0] });
    }
    next();
  },
  userCtrl.register
);
// 获取当前登录用户
router.get(
  "/user",
  [
    body("user.username").notEmpty().withMessage("用户名不能为空"),
    body("user.password")
      .notEmpty()
      .withMessage("密码不能为空")
      .bail()
      .custom(async (password,{req}) => {
        const user = await User.findOne({ username: req.body.user.username });
        if (!user) {
          return Promise.reject("账户或密码错误,请检查!");
        }
        // 比较提供的密码与数据库中存储的哈希密码
        const isMatch = await bcrypt.compare(password, user.password);
        if (!isMatch) {
          return Promise.reject("账户或密码错误,请检查!");
        }
        return true;
      }),
  ],
  (req, res, next) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array()[0] });
    }
    next();
  },
  userCtrl.getCurUser
);
// 更新当前登录用户
router.put("/user", userCtrl.updateCurUser);

module.exports = router;

这样在用户注册的时候,就可以加密后存储到数据库啦

用户登录的时候正常输入账号密码,进入解码逻辑,正常登录

posted @   JocelynFung  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
Live2D 看板娘 / Demo
点击右上角即可分享
微信分享提示