
nodejs + mongodb 編寫 restful 風格博客 api
cd nodejs-auth-mysql-rest-api
npm init -y
安裝依賴
npm install express express-validator mysql body-parser jsonwebtoken bcryptjs cors --save
這里我不用在電腦上去安裝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 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;
創建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
# 數據庫連接成功
創建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;
安裝nodemon
npm install nodemon --save-dev
修改package.json
"scripts": {
"start": "nodemon server.js"
},
運行項目
npm start
# 服務啟動成功:http://localhost:3000
# 數據庫連接成功
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
本文章轉載微信公眾號@小帥的編程筆記
nodejs + mongodb 編寫 restful 風格博客 api
表格插件wpDataTables-將 WordPress 表與 Google Sheets API 連接
手把手教你用Python和Flask創建REST API
使用 Django 和 Django REST 框架構建 RESTful API:實現 CRUD 操作
ASP.NET Web API快速入門介紹
2024年在線市場平臺的11大最佳支付解決方案
完整指南:如何在應用程序中集成和使用ChatGPT API
選擇AI API的指南:ChatGPT、Gemini或Claude,哪一個最適合你?
用ASP.NET Core 2.1 建立規范的 REST API — 緩存和并發