Express.js 是 Node.js 环境下最流行的 Web 应用程序框架之一,其模块化和可插拔的结构使得其很容易实现 RESTful API。在本文中,我们将讨论如何在 Express.js 中实现多用户的 RESTful API。
需求分析
在实现多用户的 RESTful API 之前,我们需要确定具体的需求。在本例中,我们需要实现以下功能:
- 注册用户
- 用户登录
- 认证用户
- 实现 API 的 CRUD 操作
基于以上需求,我们需要实现以下 API:
- POST /users:注册用户
- POST /users/login:用户登录
- GET /users/me:认证用户
- POST /api:创建资源
- GET /api/:id:获取资源
- PATCH /api/:id:更新资源
- DELETE /api/:id:删除资源
实现方法
- 创建应用程序
在创建应用程序之前,我们需要安装一些必须的依赖:
npm install express body-parser jsonwebtoken bcryptjs mongoose passport passport-jwt
其中,express 是 Express.js 应用程序框架,body-parser 是用于解析请求体的中间件,jsonwebtoken 是用于生成和解码用户令牌的库,bcryptjs 是用于密码哈希和比较的库,mongoose 是 MongoDB 的对象文档映射(ODM)库,passport 和 passport-jwt 用于处理用户身份验证和 JSON Web Token。
在安装了必须的依赖之后,我们可以创建我们的应用程序。
// www.javascriptcn.com code example
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const passport = require('passport');
const app = express();
// 引入配置
const keys = require('./config/keys');
// 解析请求体中间件
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// 连接 MongoDB
mongoose
.connect(keys.mongoURI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
// Passport 初始化
app.use(passport.initialize());
require('./config/passport')(passport); // 引入 passport 配置
// 路由
app.use('/users', require('./routes/users')); // 用户接口
app.use('/api', require('./routes/api')); // API 接口
// 服务器运行的端口号
const port = process.env.PORT || 3000;
// 启动服务器
app.listen(port, () => console.log(`Server running on port ${port}`));在这个应用程序中,我们首先引入必要的依赖和配置,然后初始化 MongoDB 和 Passport.js。最后,我们引入用户和 API 的路由。
- 用户模型
在我们实现用户接口之前,我们需要先创建一个用户模型。
// www.javascriptcn.com code example
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// 创建用户模型
const UserSchema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
date: { type: Date, default: Date.now }
});
module.exports = mongoose.model('User', UserSchema);在这个模型中,我们定义了用户的名字,电子邮件地址,密码和创建日期。对于密码,我们将使用 bcryptjs 库对其进行哈希。
- 用户注册和登录
接下来,我们将实现用户注册和登录接口。
// www.javascriptcn.com code example
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const passport = require('passport');
// 引入验证
const validateRegisterInput = require('../validation/register');
const validateLoginInput = require('../validation/login');
// 引入用户模型
const User = require('../models/User');
// 用户注册
router.post('/register', (req, res) => {
// 验证用户注册信息
const { errors, isValid } = validateRegisterInput(req.body);
if (!isValid) {
return res.status(400).json(errors);
}
// 验证是否存在同名用户
User.findOne({ email: req.body.email }).then(user => {
if (user) {
errors.email = '邮箱已被注册';
return res.status(400).json(errors);
} else {
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password
});
// 密码哈希
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => res.json(user))
.catch(err => console.log(err));
});
});
}
});
});
// 用户登录
router.post('/login', (req, res) => {
// 验证用户登录信息
const { errors, isValid } = validateLoginInput(req.body);
if (!isValid) {
return res.status(400).json(errors);
}
const email = req.body.email;
const password = req.body.password;
// 查找用户
User.findOne({ email }).then(user => {
if (!user) {
errors.email = '用户不存在';
return res.status(404).json(errors);
}
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
const payload = { id: user.id, name: user.name };
// 签发令牌
jwt.sign(
payload,
keys.secretOrKey,
{ expiresIn: 3600 },
(err, token) => {
res.json({
success: true,
token: 'Bearer ' + token
});
}
);
} else {
errors.password = '密码不正确';
return res.status(400).json(errors);
}
});
});
});
// 获取认证用户信息
router.get(
'/me',
passport.authenticate('jwt', { session: false }),
(req, res) => {
res.json({
id: req.user.id,
name: req.user.name,
email: req.user.email
});
}
);
module.exports = router;在这个路由中,我们引入了用户模型,验证注册和登录信息的中间件,以及生成 JSON Web Token 的库。在用户注册接口中,我们首先验证用户输入是否合法,然后检查是否存在同名用户。如果不存在同名用户,则将用户的密码哈希并保存到数据库中。在用户登录接口中,我们验证用户输入是否合法,然后在数据库中查找用户。如果用户存在,我们将检查输入的密码是否与数据库中的哈希匹配。如果匹配,我们将生成一个 JSON Web Token 并返回给客户端。
- API 模型
现在,我们将在数据库中创建一个名为 Api 的模型,用于表示我们的 API。
// www.javascriptcn.com code example
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// 创建 API 模型
const ApiSchema = new Schema({
title: { type: String, required: true },
description: String,
author: { type: Schema.Types.ObjectId, ref: 'User' },
date: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Api', ApiSchema);在这个模型中,我们定义了标题、描述、作者和创建日期。
- API 接口
最后,我们将实现用于管理 API 的接口。
// www.javascriptcn.com code example
const express = require('express');
const router = express.Router();
const passport = require('passport');
// 引入 API 模型
const Api = require('../models/Api');
// 获取所有 API
router.get('/', (req, res) => {
Api.find().populate('author', ['name', 'email']).then(apis => {
res.json(apis);
}).catch(err => console.log(err));
});
// 获取单个 API
router.get('/:id', (req, res) => {
Api.findById(req.params.id).populate('author', ['name', 'email']).then(api => {
if (!api) {
return res.status(404).json({ msg: 'API not found' });
}
res.json(api);
}).catch(err => console.log(err));
});
// 创建 API
router.post('/', passport.authenticate('jwt', { session: false }), (req, res) => {
const newApi = new Api({
title: req.body.title,
description: req.body.description,
author: req.user.id
});
newApi.save().then(api => {
res.json(api);
}).catch(err => console.log(err));
});
// 更新 API
router.patch('/:id', passport.authenticate('jwt', { session: false }), (req, res) => {
Api.findById(req.params.id).then(api => {
if (!api) {
return res.status(404).json({ msg: 'API not found' });
}
if (api.author.toString() !== req.user.id) {
return res.status(401).json({ msg: 'Not authorized' });
}
api.title = req.body.title || api.title;
api.description = req.body.description || api.description;
api.save().then(api => {
res.json(api);
}).catch(err => console.log(err));
}).catch(err => console.log(err));
});
// 删除 API
router.delete('/:id', passport.authenticate('jwt', { session: false }), (req, res) => {
Api.findById(req.params.id).then(api => {
if (!api) {
return res.status(404).json({ msg: 'API not found' });
}
if (api.author.toString() !== req.user.id) {
return res.status(401).json({ msg: 'Not authorized' });
}
api.delete().then(() => {
res.json({ msg: 'API deleted' });
}).catch(err => console.log(err));
}).catch(err => console.log(err));
});
module.exports = router;在这个路由中,我们首先引入 API 模型和 Passport.js。在获取所有 API 接口中,我们使用 populate() 方法将 API 的作者信息展开。在创建 API 接口中,我们使用 passport.authenticate() 中间件验证用户是否已经登录。在更新和删除 API 接口中,我们还检查请求的用户是否是 API 的作者。
这样,我们就完成了在 Express.js 中实现多用户的 RESTful API 的过程。本例中的代码可以作为示例,帮助你快速入门 Express.js。同时,我们也希望本文对你在实现多用户的 RESTful API 中有所帮助。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/6780cf28ce7f4861254a5fe0