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;

第三步:在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

本文章轉載微信公眾號@小帥的編程筆記

上一篇:

nodejs + mongodb 編寫 restful 風格博客 api

下一篇:

Ocelot:.NET開源API網關提供路由管理、服務發現、鑒權限流等功能
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費