大部分的项目中都存在登录注册这个模块,除了常规的操作之外,比较重要的一点,我们需要对用户的密码进行加密之后再存储。
除了考虑数据库被黑掉的情况,作为一个程序员来说,职业操守也要求我们要做密码的加密,这属于用户的隐私,不加密的话,几乎所有的技术人员都可以知道用户的密码,这是不合理的。
作为一个前端,可能在正式项目中,不需要由前端来考虑密码的加密,但是前端多了解一些后端的知识,对你自己肯定是有帮助的。
因为我本身是做前端的,所以本文章中,关于后端的技术选型以Nodejs的Express框架为例,数据库选择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和一个password。mongodb中有一个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方法携带的username和password。之后。通过create方法来添加新数据。
为什么要包裹一个try catch呢,因为我们给username设置了唯一unique。如果新注册的username和数据库中已存在的重复,就会报错,所以我们在catch中给前端一个反馈。
这样就完成了基本的注册逻辑。
那么怎么加密呢
先通过npm下载一下bcrypt.js
npm install bcryptjs --save
引入
const bcrypt = require("bcryptjs");
bcrypt.js提供了两个核心方法,hashSync和compareSync,hashSync是加密用的,compareSync是用来做验证的。
那么怎么使用呢。
在设定集合规则的时候
const UserAccountSchema = new mongoose.Schema({
username: {
type: String,
unique: true,
},
password: {
type: String,
set(val) {
return bcrypt.hashSync(val);
},
},
});
每个字段都有提供给set属性,跟Vue中用来做双向绑定的getter和setter一样。
所以,我们选择在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方法携带的参数username和password。
然后通过mongodb提供的findOne方法通过username进行查询,因为每个username都是唯一的。
如果查不到值,就给前端反馈一个用户名不存在。如果查到值了,说明username是存在的,就要验证一下密码password对不对了。
通过bcrypt.compareSync()来验证,第一个参数是未加密的值,就是前端传过来的,用户登录时候输入的明文密码。第二个参数是查到的加密后的值,上面我们已经通过findOne进行查询了。在有值的前提下,才会执行到这里。
然后就是判断返回值是true还是false了。true代表未加密的值和加密后的值是一致的,用户登录成功,false代表不一致,用户输入的密码不对。
然后给前端相应的反馈即可。
这样我们就通过在Express + Mongodb在技术栈下,通过bcrypt.js对密码进行加密和验证的过程。
本文章需要一些Express和Mongodb的基础。
全部代码如下:
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/


被折叠的 条评论
为什么被折叠?



