所有文章 > API开发 > node.js + express + docker + mysql + jwt 实现用户管理restful api

node.js + express + docker + mysql + jwt 实现用户管理restful api

今天我们用node.js + express + docker + mysql + jwt来搞一个简单版的用户管理restful api,里面有基础的用户注册、用户登录和获取用户信息的功能。其中用到了express的路由,使用express-validator作为表单验证器,用docker运行mysql容器,密码的加密,jwt生成用户token等等。下面来搞起来

用到的技术

第一步:创建项目目录

mkdir nodejs-auth-mysql-rest-api
cd nodejs-auth-mysql-rest-api
npm init -y

安装依赖

npm install express express-validator mysql body-parser jsonwebtoken bcryptjs cors --save
  • express
    • 启动基本的http服务
  • express-validator
    • 用来验证表单是否合法
  • mysql
    • 连接mysql数据库,存储数据,查询数据
  • body-parser
    • 解析post请求体的数据
  • jsonwebtoken
    • 用于生成jwt的token
  • bcryptjs
    • 加密用户注册的密码
  • cors
    • 允许跨域的请求访问

第二步:创建数据库和表

这里我不用在电脑上去安装mysql数据库,我们使用docker的方式在本机上运行一个mysql容器,需要熟悉一些基本的docker使用。

创建数据文件夹

mkdir data

创建mysql容器

docker run -v "$PWD/data":/var/lib/mysql --name dev-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
  • docker run
    • 运行docker容器
  • -v “$PWD/data”:/var/lib/mysql
    • 将容器内的数据存储目录映射到宿主机的目录,避免容器关闭导致的数据丢失
  • –name dev-mysql
    • 容器名称
  • -p 3306:3306
    • 将容器内的3306端口映射到宿主机上,这里我是为了方便,正常是不会这样映射,因为很危险。
  • -e MYSQL_ROOT_PASSWORD=123456
    • 将root密码设置为123456
  • -d
    • 将容器在后台运行
  • mysql:5.7
    • 容器的镜像和镜像版本

查看运行容器

docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b1808287e831 mysql:5.7 "docker-entrypoint.s…" 15 seconds ago Up 12 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp dev-mysql

停止容器

docker stop b1808287e831

查看所有容器

docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b1808287e831 mysql:5.7 "docker-entrypoint.s…" 15 minutes ago Exited (0) 10 seconds ago dev-mysql

启动容器

docker start b1808287e831

创建数据库和表

在目录中创建database.sql,用户创建数据表

CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
`password` varchar(200) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY email (email)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;

执行下面命令在容器内创建数据库和表

# 将sql文件拷贝进容器内
docker cp $PWD/database.sql b1808287e831:/database.sql
# 进入容器内
docker exec -it b1808287e831 bin/bash
# 连接mysql 输入密码
mysql -u root -p
# 显示所有数据数据库
show databases;
# 创建数据库
create database `node-app`;
# 使用数据库
use `node-app`;
# 导入数据表
source /database.sql;
# 退出mysql
exit;
# 退出容器
exit;

第三步:在nodejs中连接数据库

创建dbConnection.js

const mysql = require('mysql');

const conn = mysql.createConnection({
host: '127.0.0.1',
user: 'root',
password: '123456',
database: 'node-app'
});

conn.connect(function(err) {
if (err) throw err;
console.log('数据库连接成功');
});

module.exports = conn;

测试是否能连接成功

node dbConnection.js
# 数据库连接成功

第四步:创建express服务

创建server.js

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const indexRouter = require('./router.js');

const app = express();

app.use(express.json());

app.use(bodyParser.json());

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

app.use(cors());

app.use('/api', indexRouter);

// 处理错误
app.use((err, req, res, next) => {
// console.log(err);
err.statusCode = err.statusCode || 500;
err.message = err.message || "Internal Server Error";
res.status(err.statusCode).json({
message: err.message,
});
});

app.listen(3000,() => console.log(`服务启动成功:http://localhost:3000`));

第五步:创建路由和验证器

创建validation.js文件

const { check } = require('express-validator');

exports.signupValidation = [
check('name', '请输入用户名').not().isEmpty(),
check('email', '请输入合法的邮箱').isEmail(),
check('password', '密码至少是6位哦').isLength({ min: 6 })
]

exports.loginValidation = [
check('email', '请输入合法的邮箱').isEmail(),
check('password', '密码至少是6位哦').isLength({ min: 6 })
]

创建router.js文件

const express = require('express');
const router = express.Router();
const db = require('./dbConnection');
const { signupValidation, loginValidation } = require('./validation');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');

const JWT_SECRET = 'my-secret'

router.post('/register', signupValidation, (req, res, next) => {
db.query(
`SELECT * FROM users WHERE LOWER(email) = LOWER(${db.escape(
req.body.email
)});`,
(err, result) => {
if (result.length) {
return res.status(409).send({
msg: '邮箱已被注册'
});
} else {
// 如果可以注册,
bcrypt.hash(req.body.password, 10, (err, hash) => {
if (err) {
return res.status(500).send({
msg: err
});
} else {
// 密码加密后,存入数据库
db.query(
`INSERT INTO users (name, email, password) VALUES ('${req.body.name}', ${db.escape(
req.body.email
)}, ${db.escape(hash)})`,
(err, result) => {
if (err) {
return res.status(400).send({
msg: err
});
}
return res.status(201).send({
msg: '用户注册成功'
});
}
);
}
});
}
}
);
});

router.post('/login', loginValidation, (req, res, next) => {
db.query(
`SELECT * FROM users WHERE email = ${db.escape(req.body.email)};`,
(err, result) => {
// 用户不存在
if (err) {
// throw err;
return res.status(400).send({
msg: err
});
}
if (!result.length) {
return res.status(401).send({
msg: '用户名或密码错误'
});
}
// 检查密码是否正确
bcrypt.compare(
req.body.password,
result[0]['password'],
(bErr, bResult) => {
// 密码错误
if (bErr) {
// throw bErr;
return res.status(401).send({
msg: '用户名或密码错误'
});
}
if (bResult) {
const token = jwt.sign({ id: result[0].id }, JWT_SECRET, { expiresIn: '1h' });
db.query(
`UPDATE users SET last_login = now() WHERE id = '${result[0].id}'`
);
return res.status(200).send({
msg: '登陆成功',
token,
user: result[0]
});
}
return res.status(401).send({
msg: '用户名或密码错误'
});
}
);
}
);
});

router.post('/get-user', signupValidation, (req, res, next) => {
if (
!req.headers.authorization ||
!req.headers.authorization.startsWith('Bearer') ||
!req.headers.authorization.split(' ')[1]
) {
return res.status(422).json({
message: "缺少Token",
});
}
const theToken = req.headers.authorization.split(' ')[1];
const decoded = jwt.verify(theToken, JWT_SECRET);
db.query('SELECT * FROM users where id=?', decoded.id, function (error, results, fields) {
if (error) throw error;
return res.send({ error: false, data: results[0], message: '请求成功' });
});
});

module.exports = router;

第六步:运行Express服务

安装nodemon

npm install nodemon --save-dev

修改package.json

"scripts": {
"start": "nodemon server.js"
},

运行项目

npm start
# 服务启动成功:http://localhost:3000
# 数据库连接成功

第七步:使用postman测试

注册用户

POST - http://localhost:3000/api/register

查看数据库是否有数据

登陆

POST - http://localhost:3000/api/login

获取用户信息

POST - http://localhost:3000/api/get-user

源码

Github:https://github.com/cmdfas/nodejs-auth-mysql-rest-api

本文章转载微信公众号@小帅的编程笔记

#你可能也喜欢这些API文章!