mysql salt bcrypt_bcrypt:加 salt 的 hash《 Node.js:基于 Token 的身份验证 》

给项目安装个包 ... 名字是 bcrypt .. 可以使用 npm 或者 yarn 去安装 ..

yarn add bcrypt

然后再回到项目 .. 打开 index.js ... 先导入刚才安装的 bcrypt 这个包 ..

添加一个 password ... 它表示要 hash 的用户的密码 ..

再用一下 bcrypt 的 genSalt .. 可以先在 hash 之前生成点要加的盐 .. 其实就是一串随机的字符 ..

它的第一个参数是 saltRounds ... 这个值越大就越安全一些 ... 默认它的值是 10 .. 然后是一个回调 .. 第一个参数是出现的错误,可以用 error 表示 .. 第二个参数是 genSalt 生成的 salt ..

可以在控制台上输出生成的 salt ..

在这个回调里,我们可以再用一下 bcrypt 的 hash 方法,去 hash 指定的字符 .. 它的第一个参数就是要 hash 的字符 ... 比如可以是用户提交过来的密码 .. 第二个参数是 salt .. 这个 salt 是用 genSalt 生成的 ... 可以使用 salt 来表示 ..

第三个参数是个回调 .. error 表示错误 .. hash 表示 hash 之后的结果 .. 我们可以把它也输出到控制台上看一下 ..

保存 ... 回到命令行... 执行一下 node index.js

上面输出的是生成的 salt,还有 hash 了指定字符外加 salt 之后的这个 hash ... 再执行几次 ... 你会发现,每次执行输出的结果都不一样 .. 因为 hash 的时候用的 salt 每次都会不一样 ..

这个 hash 的结果里面,有一部分表示的是在 hash 的时候使用的 salt ...

compare

假设我们存储在数据库里的用户的密码是这个 hash ... 现在我们可以比较一下,用户登录的时候输入的密码,跟我们在数据库里存储的 hash 之后的密码是否匹配 ..

复制一下这个 hash ... 回到 index.js ... 添加一个 hashPassword ... 它的值假设就是我们存储在数据库里的 hash 之后的用户密码 ..

再添加一个 userInputPassword ... 它的值表示的是用户请求验证身份的时候提供给我们的密码 ...

下面我们可以使用 bcrypt 的 compare 方法去比较一下 ... 先是用户输入的密码 .. userInputPassword .. 然后是一个 hash,这个 hash 应该是我们存储在数据库里的 hash 之后的用户密码 ..

它会返回 Promise ... 可以用一个 then ... result 表示比较的结果 ... 再把这个结果输出到控制台上 ..

回到命令行 .. 执行一下 node index.js ..

比较的结果是 true ... 回来再修改一下 .. 比如用户输入的是 password1 .. 再回来执行一下 ... 这次会显示 false ... 表示用户输入的密码跟我们存储的 hash 之后的密码不匹配 ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,基于Node.js的图书管理系统可以分为以下几个模块: 1. 用户模块:实现用户的注册、登录、修改个人信息等功能。 2. 图书模块:实现图书的添、修改、删除、查询等功能。 3. 借阅模块:实现用户的借阅、归还操作,并提供相应的借阅记录查询功能。 4. 管理员模块:实现管理员的登录、图书管理、用户管理等功能。 下面是一个简单的实现示例: 1. 创建项目并初始化 ```bash mkdir book-management cd book-management npm init -y ``` 2. 安装依赖 ```bash npm install express body-parser mongoose jsonwebtoken bcryptjs cors ``` 3. 创建数据库模型 在项目根目录下创建`models`目录,并在该目录下创建`user.js`、`book.js`和`borrow.js`三个文件,分别表示用户、图书和借阅记录的数据库模型。 ```javascript // user.js const mongoose = require('mongoose'); const bcrypt = require('bcryptjs'); const UserSchema = new mongoose.Schema({ username: { type: String, required: true }, password: { type: String, required: true }, email: { type: String }, avatar: { type: String } }); UserSchema.pre('save', async function(next) { try { const salt = await bcrypt.genSalt(10); const hash = await bcrypt.hash(this.password, salt); this.password = hash; next(); } catch (error) { next(error); } }); UserSchema.methods.isValidPassword = async function(password) { try { return await bcrypt.compare(password, this.password); } catch (error) { throw error; } }; const User = mongoose.model('User', UserSchema); module.exports = User; ``` ```javascript // book.js const mongoose = require('mongoose'); const BookSchema = new mongoose.Schema({ title: { type: String, required: true }, author: { type: String, required: true }, description: { type: String }, cover: { type: String }, ISBN: { type: String, required: true, unique: true }, category: { type: String }, quantity: { type: Number, default: 0 }, borrow: { type: Number, default: 0 } }); const Book = mongoose.model('Book', BookSchema); module.exports = Book; ``` ```javascript // borrow.js const mongoose = require('mongoose'); const BorrowSchema = new mongoose.Schema({ user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, book: { type: mongoose.Schema.Types.ObjectId, ref: 'Book', required: true }, borrowDate: { type: Date, required: true }, returnDate: { type: Date } }); const Borrow = mongoose.model('Borrow', BorrowSchema); module.exports = Borrow; ``` 4. 创建路由 在项目根目录下创建`routes`目录,并在该目录下创建`auth.js`、`book.js`和`borrow.js`三个文件,表示用户认证、图书管理和借阅记录管理的路由。 ```javascript // auth.js const express = require('express'); const jwt = require('jsonwebtoken'); const bcrypt = require('bcryptjs'); const User = require('../models/user'); const router = express.Router(); router.post('/register', async (req, res, next) => { try { const { username, password, email, avatar } = req.body; const existingUser = await User.findOne({ username }); if (existingUser) { return res.status(400).json({ message: 'Username already exists' }); } const user = new User({ username, password, email, avatar }); await user.save(); const token = jwt.sign({ user }, process.env.SECRET_KEY); res.status(201).json({ user, token }); } catch (error) { next(error); } }); router.post('/login', async (req, res, next) => { try { const { username, password } = req.body; const user = await User.findOne({ username }); if (!user) { return res.status(404).json({ message: 'User not found' }); } const isMatch = await user.isValidPassword(password); if (!isMatch) { return res.status(401).json({ message: 'Wrong password' }); } const token = jwt.sign({ user }, process.env.SECRET_KEY); res.status(200).json({ user, token }); } catch (error) { next(error); } }); module.exports = router; ``` ```javascript // book.js const express = require('express'); const Book = require('../models/book'); const router = express.Router(); router.get('/', async (req, res, next) => { try { const books = await Book.find(); res.status(200).json(books); } catch (error) { next(error); } }); router.post('/', async (req, res, next) => { try { const book = new Book(req.body); await book.save(); res.status(201).json(book); } catch (error) { next(error); } }); router.put('/:id', async (req, res, next) => { try { const { id } = req.params; const book = await Book.findByIdAndUpdate(id, req.body, { new: true }); if (!book) { return res.status(404).json({ message: 'Book not found' }); } res.status(200).json(book); } catch (error) { next(error); } }); router.delete('/:id', async (req, res, next) => { try { const { id } = req.params; const book = await Book.findByIdAndDelete(id); if (!book) { return res.status(404).json({ message: 'Book not found' }); } res.status(200).json(book); } catch (error) { next(error); } }); module.exports = router; ``` ```javascript // borrow.js const express = require('express'); const Borrow = require('../models/borrow'); const router = express.Router(); router.get('/', async (req, res, next) => { try { const borrows = await Borrow.find().populate('user').populate('book'); res.status(200).json(borrows); } catch (error) { next(error); } }); router.post('/', async (req, res, next) => { try { const { user, book, borrowDate } = req.body; const borrow = new Borrow({ user, book, borrowDate }); await borrow.save(); res.status(201).json(borrow); } catch (error) { next(error); } }); router.put('/:id', async (req, res, next) => { try { const { id } = req.params; const borrow = await Borrow.findByIdAndUpdate(id, req.body, { new: true }); if (!borrow) { return res.status(404).json({ message: 'Borrow record not found' }); } res.status(200).json(borrow); } catch (error) { next(error); } }); router.delete('/:id', async (req, res, next) => { try { const { id } = req.params; const borrow = await Borrow.findByIdAndDelete(id); if (!borrow) { return res.status(404).json({ message: 'Borrow record not found' }); } res.status(200).json(borrow); } catch (error) { next(error); } }); module.exports = router; ``` 5. 创建服务器 在项目根目录下创建`server.js`文件,并在该文件中创建服务器,并将用户认证、图书管理和借阅记录管理的路由挂载到相应的路径上。 ```javascript const express = require('express'); const bodyParser = require('body-parser'); const mongoose = require('mongoose'); const cors = require('cors'); const authRouter = require('./routes/auth'); const bookRouter = require('./routes/book'); const borrowRouter = require('./routes/borrow'); require('dotenv').config(); const app = express(); const port = process.env.PORT || 3000; const uri = process.env.MONGODB_URI || 'mongodb://localhost:27017/book-management'; mongoose.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => { console.log('Connected to MongoDB'); }) .catch((error) => { console.error(error); }); app.use(cors()); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use('/auth', authRouter); app.use('/books', bookRouter); app.use('/borrows', borrowRouter); app.listen(port, () => { console.log(`Server is running on port ${port}`); }); ``` 6. 运行服务器 使用以下命令启动服务器: ```bash node server.js ``` 然后可以使用Postman等API测试工具测试API接口的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值