Node express MongoDB 註冊與登出api

註冊使用到以下功能

  • cors 跨來源資源共用
  • bcryptjs密碼加密
  • jsonwebtoken用戶身份驗證

使用者定義Schema

請參閱
在models資料夾內新增 userModel.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
const mongoose = require('mongoose')
const bcrypt = require('bcryptjs')
const moment = require('moment')
moment().format();
const timezone = -(new Date().getTimezoneOffset() / 60) + 8;
const time = moment(Date.now() + (timezone * 60 * 60 * 1000)).format('YYYY-MM-DDT HH:mm').toString();
//console.log('timezone', timezone)

const userSchema = mongoose.Schema(
{
username: {
type: String,
required: [true, "請輸入使用者2~30字符"],
trim: true,
match: [
/^.{2,30}$/,
'Please add a valid name 2~30字符',
],
},
email: {
type: String,
required: true,
match: [
/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/,
'Please add a valid email',
],
},
password: {
type: String,
required: [true],
trim: true,
},
created:
{
type: String,
default: time
},
token: {
type: String,
}
},

)
//findByEmail 函式
userSchema.statics.findByEmail =async (email) =>{
//查找User 是否有該email
const user = await User.findOne({ email })
//如果有
if (user) { throw new Error('已經有該用戶!') }
return user
}

const User = mongoose.model('User', userSchema);

module.exports = User;

註冊與登入

驗證的路由必須要 middleware

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//verifyToken
const verifyToken = (req, res, next) =>
{
const bearerHeader = req.headers.authorization;
if (typeof bearerHeader !== 'undefined') {
const bearer = bearerHeader.split(' ');
const bearerToken = bearer[1];
req.token = bearerToken;
next();
}
else {
req.send({result:'令牌無效!'})
}
}
module.exports = verifyToken;

註冊與登入& 驗證

引入 userModel.js
引入jwt,bcrypt,verifyToken
bcrypt.hashSync :bcrypt加密
bcrypt.compare() :bcrypt驗證密碼
引入 jwt sign()驗證 token
jwt & bcrypt 筆記

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const express = require('express')
const verifyToken = require('../middleware/token')
const User = require('../models/userModel')
const jwt = require('jsonwebtoken')
const bcrypt = require('bcryptjs')
const router = express.Router()

//註冊
router.post('/register', async(req, res) =>
{
try {
/*
#swagger.summary='註冊',
#swagger.description = '' */
/* #swagger.parameters['body'] = {
in: 'body',
description: '',
required: true,
schema: { $ref: "#/definitions/AddUser" }
} */

/* #swagger.security = [{
"apiKeyAuth": []
}] */
const data = new User(req.body);
//註冊時,Email使用 findByEmail 函式驗證
const email = await User.findByEmail(req.body.email)
data.password = bcrypt.hashSync(req.body.password, 12);

const token = jwt.sign({ _id: data._id ,username: data.username,email: data.email}, 'RESTFULAPI',{expiresIn: "24h"}).toString();
let userArr = {
username: data.username,
email: data.email,
password: data.password,
created: data.created,
token:token
}

const user = await User.create(userArr);
res.status(200).json(user);
}
catch (error) {
res.status(500).json({message: error.message})
}
})


//登入
router.post('/login',async (req, res) =>{
const { email, password } = req.body;
try {
/*
#swagger.summary='登入',
#swagger.description = '' */

/* #swagger.parameters['body'] = {
in: 'body',
description: '',
required: true,
schema: { $ref: "#/definitions/Login" }
} */

/* #swagger.security = [{
"apiKeyAuth": []
}] */
let user = await User.findOne({email});
if (!user)
return res.status(400).json({message: "用戶不存在"});

const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch)
return res.status(400).json({message: "密碼錯誤 !"});

const payload = {
user: {id: user.id}
};

jwt.sign(payload,user.email,{expiresIn: 3600},(err, token) => {
if (err) throw err;
res.status(200).json({token});
}
);
}
catch (e) {
console.error(e);
res.status(500).json({
message: "伺服器錯誤!"
});
}
})


//users驗證
router.delete('/users/:id', verifyToken,async(req, res) =>{
try {
/*
#swagger.tags = ['以下請先登入'],
#swagger.summary='刪除使用者',
#swagger.description = '' */
const {id} = req.params;
const user = await User.findByIdAndDelete(id);
if(!user){
return res.status(404).json({message: `沒有發現任何使用者 ${id}`})
}
res.status(200).json(user );

} catch (error) {
res.status(500).json({message: error.message})
}
})


router.post("/welcome", verifyToken, (req, res) =>
{
/*
#swagger.tags = ['以下請先登入'],
#swagger.summary='歡迎畫面',
#swagger.description = '' */
console.log('req.body', req.body)
res.status(200).send("Welcome 🙌 ");
});

module.exports = router;

node express jwt 註冊與登出
bcrypt
bcrypt筆記本
Node 實作 jwt 驗證 API
How To Implement API Authentication with JSON Web Tokens and Passport
OAuth 2.0
OAuth 2.0