bcrypt.js实现对登录注册中密码的加密存储和验证

41 篇文章 2 订阅
10 篇文章 0 订阅

大部分的项目中都存在登录注册这个模块,除了常规的操作之外,比较重要的一点,我们需要对用户的密码进行加密之后再存储。
除了考虑数据库被黑掉的情况,作为一个程序员来说,职业操守也要求我们要做密码的加密,这属于用户的隐私,不加密的话,几乎所有的技术人员都可以知道用户的密码,这是不合理的。

作为一个前端,可能在正式项目中,不需要由前端来考虑密码的加密,但是前端多了解一些后端的知识,对你自己肯定是有帮助的。

因为我本身是做前端的,所以本文章中,关于后端的技术选型以NodejsExpress框架为例,数据库选择Mongodb

那么,怎么进行数据的加密呢?

在早些年,可能MD5的加密方式比较流行。大家对加密的最基本的需求是不可逆。如果可逆的话,对于技术人员来说,依然和明文没什么区别。

MD5虽然是不可逆的,但是它有一个唯一的对应值,比如a在加密之后对应123,b加密之后对应456,这个是固定的。所以,当越来越多的加密过程被记录下来之后,绘制成一张表。就可以找到相应的对应关系。

再之后,有一些针对MD5的补救的措施,比如“加盐”,就是在MD5加密过程中,多包裹一层字符串作为密钥。

今天我们介绍的加密方式是bcrypt.js,不需要做“加盐”处理。

首先我们需要通过Express构造一套后端服务。

npm install express --save

const express = require('express');
const app = express();

app.use(express.urlencoded({ extended: true }));
app.use(express.json());

app.listen(9000, () => {
  console.log("server running!");
});

这样就开了一个端口为9000的后端服务。

然后是数据库的部分

npm install mongoose --save

Node中我们通过mongoose来操作mongodb数据库

const express = require('express');
const mongoose = require("mongoose");
const app = express();

app.use(express.urlencoded({ extended: true }));
app.use(express.json());

// 数据库连接
mongoose
  .connect("mongodb://localhost/UserAccount")
  .then(() => {
    console.log("数据库连接成功");
  })
  .catch((err) => {
    console.log("数据库连接失败", err);
  });

// 设定集合规则
const UserAccountSchema = new mongoose.Schema({
  username: {
    type: String,
    unique: true,
  },
  password: {
    type: String,
  },
});

// 创建集合并应用规则
const UserAccount = mongoose.model("Course", UserAccountSchema);

app.listen(9000, () => {
  console.log("server running!");
});

怎么去配置Mongodb数据库,这里就不解释了,不是重点。

连接UserAccount表之后,设定集合规则,创建集合。

数据库表的设计,就简单一些,只有一个username和一个passwordmongodb中有一个unique字段,来表示不能重复。理论上账号是不允许重复的。

这样,我们就完成了基本的操作。我们来写一个注册的接口。

app.post("/register", async (req, res) => {
  const {
    body: { username, password },
  } = req;
  try {
    const result = await UserAccount.create({
      username,
      password,
    });
    res.send(result);
  } catch (error) {
    return res.status(400).send({
      message: "用户名已存在",
    });
  }
});

这是一个最基本的注册逻辑。解构出POST方法携带的usernamepassword。之后。通过create方法来添加新数据。

为什么要包裹一个try catch呢,因为我们给username设置了唯一unique。如果新注册的username和数据库中已存在的重复,就会报错,所以我们在catch中给前端一个反馈。

这样就完成了基本的注册逻辑。

那么怎么加密呢

先通过npm下载一下bcrypt.js

npm install bcryptjs --save

引入

const bcrypt = require("bcryptjs");

bcrypt.js提供了两个核心方法,hashSynccompareSynchashSync是加密用的,compareSync是用来做验证的。

那么怎么使用呢。

在设定集合规则的时候

const UserAccountSchema = new mongoose.Schema({
  username: {
    type: String,
    unique: true,
  },
  password: {
    type: String,
    set(val) {
      return bcrypt.hashSync(val);
    },
  },
});

每个字段都有提供给set属性,跟Vue中用来做双向绑定的gettersetter一样。

所以,我们选择在set中对password进行加密。

bcrypt.hashSync()中传入要加密的值即可。

在这里插入图片描述
password就会被加密成这样。

我们在设定集合规则的时候,在字段的set属性中进行加密,就能保证,此表的所有数据,在新增数据时,都会进行加密。

这样加密就完成了,登录的时候怎么进行验证呢?

我们再写一个登录接口。

app.post("/login", async (req, res) => {
  const {
    body: { username, password },
  } = req;
  const user = await UserAccount.findOne({
    username,
  });
  if (!user) {
    return res.status(400).send({
      message: "用户名不存在",
    });
  }
  const isPasswordValid = bcrypt.compareSync(password, user.password);
  if (!isPasswordValid) {
    return res.status(400).send({
      message: "密码错误",
    });
  }
	res.send(user)
});

在登录接口login中首先做的事情肯定是解构出POST方法携带的参数usernamepassword

然后通过mongodb提供的findOne方法通过username进行查询,因为每个username都是唯一的。

如果查不到值,就给前端反馈一个用户名不存在。如果查到值了,说明username是存在的,就要验证一下密码password对不对了。

通过bcrypt.compareSync()来验证,第一个参数是未加密的值,就是前端传过来的,用户登录时候输入的明文密码。第二个参数是查到的加密后的值,上面我们已经通过findOne进行查询了。在有值的前提下,才会执行到这里。

然后就是判断返回值是true还是false了。true代表未加密的值和加密后的值是一致的,用户登录成功,false代表不一致,用户输入的密码不对。

然后给前端相应的反馈即可。

这样我们就通过在Express + Mongodb在技术栈下,通过bcrypt.js对密码进行加密和验证的过程。

本文章需要一些ExpressMongodb的基础。

全部代码如下:

const express = require("express");
// 引入mongoose第三方模块, 用来操作mongodb数据库
const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const app = express();

app.use(express.urlencoded({ extended: true }));
app.use(express.json());

// 数据库连接
mongoose
  .connect("mongodb://localhost/UserAccount")
  .then(() => {
    console.log("数据库连接成功");
  })
  .catch((err) => {
    console.log("数据库连接失败", err);
  });

// 设定集合规则
const UserAccountSchema = new mongoose.Schema({
  username: {
    type: String,
    unique: true,
  },
  password: {
    type: String,
    set(val) {
      return bcrypt.hashSync(val);
    },
  },
});

// 创建集合并应用规则
const UserAccount = mongoose.model("Course", UserAccountSchema);

app.all("*", (req, res, next) => {
  // 解决跨域问题
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader("Access-Control-Allow-Headers", "*");
  next();
});

app.post("/register", async (req, res) => {
  const {
    body: { username, password },
  } = req;
  try {
    const result = await UserAccount.create({
      username,
      password,
    });
    res.send(result);
  } catch (error) {
    return res.status(400).send({
      message: "用户名已存在",
    });
  }
});

app.post("/login", async (req, res) => {
  const {
    body: { username, password },
  } = req;
  const user = await UserAccount.findOne({
    username,
  });
  if (!user) {
    return res.status(400).send({
      message: "用户名不存在",
    });
  }
  const isPasswordValid = bcrypt.compareSync(password, user.password);
  if (!isPasswordValid) {
    return res.status(400).send({
      message: "密码错误",
    });
  }
  const token = jwt.sign(
    {
      id: String(user._id),
    },
    SECRET
  );
  res.send({
    user,
    token,
  });
});

app.listen(9000, () => {
  console.log("server running!");
});


欢迎大家关注我的公众号,有很多关于前端的内容哦
QQ:505417246
WX:18331092918
公众号:Code程序人生
B站账号:LuckyRay123
个人博客:http://rayblog.ltd/

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
NestJS 是一个非常强大的后端框架,它提供了许多工具和库来帮助我们实现用户注册、登录和验证功能。下面是一个基本的 NestJS 用户注册、登录和验证功能的实现步骤: 1. 安装必要的库 首先,我们需要安装一些必要的库: ```bash npm install @nestjs/passport passport passport-local bcryptjs jsonwebtoken ``` 这些库将帮助我们实现身份验证密码加密。 2. 创建用户模型 我们需要创建一个用户模型,用于存储用户的用户名和密码。在 NestJS ,我们可以使用 Mongoose 来定义和操作 MongoDB 数据库。 ```bash nest g class users/user ``` ```typescript import * as mongoose from 'mongoose'; export const UserSchema = new mongoose.Schema({ username: String, password: String, }); export interface User extends mongoose.Document { id: string; username: string; password: string; } ``` 3. 创建用户服务 我们需要创建一个用户服务,用于处理用户注册、登录和验证逻辑。 ```bash nest g service users/user ``` ```typescript import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; import { User } from './user.interface'; import * as bcrypt from 'bcryptjs'; @Injectable() export class UserService { constructor(@InjectModel('User') private readonly userModel: Model<User>) {} async findByUsername(username: string): Promise<User | undefined> { return await this.userModel.findOne({ username }).exec(); } async create(user: User): Promise<User> { const salt = bcrypt.genSaltSync(); user.password = bcrypt.hashSync(user.password, salt); const newUser = new this.userModel(user); return await newUser.save(); } async comparePassword(password: string, hash: string): Promise<boolean> { return bcrypt.compareSync(password, hash); } } ``` 4. 创建身份验证策略 我们需要创建一个身份验证策略,用于验证用户的用户名和密码。在 NestJS ,我们可以使用 Passport.js实现身份验证。 ```bash nest g guard auth/auth ``` ```typescript import { Injectable } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Injectable() export class AuthGuardLocal extends AuthGuard('local') {} ``` 5. 创建身份验证模块 我们需要创建一个身份验证模块,用于注册身份验证策略和提供身份验证服务。在 NestJS ,我们可以使用 Passport.js 和 JWT 来实现身份验证。 ```bash nest g module auth ``` ```typescript import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { PassportModule } from '@nestjs/passport'; import { JwtModule } from '@nestjs/jwt'; import { AuthService } from './auth.service'; import { AuthController } from './auth.controller'; import { UserService } from '../users/user.service'; import { UserSchema } from '../users/user.model'; import { JwtStrategy } from './jwt.strategy'; import { LocalStrategy } from './local.strategy'; @Module({ imports: [ MongooseModule.forFeature([{ name: 'User', schema: UserSchema }]), PassportModule, JwtModule.register({ secret: 'secret', signOptions: { expiresIn: '1d' }, }), ], providers: [AuthService, UserService, LocalStrategy, JwtStrategy], controllers: [AuthController], }) export class AuthModule {} ``` 6. 创建身份验证控制器 我们需要创建一个身份验证控制器,用于处理用户注册、登录和验证请求。 ```bash nest g controller auth ``` ```typescript import { Controller, Post, UseGuards, Request, Body, Get, } from '@nestjs/common'; import { AuthGuardLocal } from './auth.guard'; import { AuthService } from './auth.service'; import { UserService } from '../users/user.service'; import { User } from '../users/user.interface'; import { JwtAuthGuard } from './jwt.guard'; @Controller() export class AuthController { constructor( private authService: AuthService, private userService: UserService, ) {} @UseGuards(AuthGuardLocal) @Post('auth/login') async login(@Request() req) { return this.authService.login(req.user); } @Post('auth/register') async register(@Body() user: User) { return this.userService.create(user); } @UseGuards(JwtAuthGuard) @Get('profile') async getProfile(@Request() req) { return req.user; } } ``` 7. 创建身份验证策略 我们需要创建一个身份验证策略,用于验证用户的 JWT token。在 NestJS ,我们可以使用 Passport.js 和 JWT 来实现身份验证。 ```bash nest g guard auth/jwt ``` ```typescript import { Injectable } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Injectable() export class JwtAuthGuard extends AuthGuard('jwt') {} ``` 8. 创建身份验证策略 我们需要创建一个身份验证策略,用于验证用户的用户名和密码。在 NestJS ,我们可以使用 Passport.js实现身份验证。 ```bash nest g guard auth/local ``` ```typescript import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-local'; import { AuthService } from './auth.service'; @Injectable() export class LocalStrategy extends PassportStrategy(Strategy) { constructor(private authService: AuthService) { super(); } async validate(username: string, password: string): Promise<any> { const user = await this.authService.validateUser(username, password); if (!user) { return false; } return user; } } ``` 9. 创建 JWT 策略 我们需要创建一个 JWT 策略,用于验证用户的 JWT token。在 NestJS ,我们可以使用 Passport.js 和 JWT 来实现身份验证。 ```typescript import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; import { UserService } from '../users/user.service'; import { User } from '../users/user.interface'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor(private readonly userService: UserService) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: 'secret', }); } async validate(payload: any): Promise<User> { return await this.userService.findByUsername(payload.username); } } ``` 现在我们已经完成了 NestJS 用户注册、登录和验证功能的实现。我们可以通过发送 POST 请求到 `/auth/register` 端点来注册新用户,通过发送 POST 请求到 `/auth/login` 端点来登录,通过发送 GET 请求到 `/profile` 端点来获取用户信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CreatorRay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值