-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauthenticate.js
More file actions
135 lines (130 loc) · 4.47 KB
/
authenticate.js
File metadata and controls
135 lines (130 loc) · 4.47 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
const jwt = require("jsonwebtoken");
const { initDatabase, md5hash, generateSalt } = require("./database");
require("dotenv").config();
const jwtServerSecret = process.env.JWTSECRET || "XJA";
// 肯定不能是XJA啊
const db = initDatabase();
class Authenticate {
static async register(username, email, password) {
try {
if (!username || !email || !password) {
throw new Error("请提供用户名、邮箱、密码,缺一不可");
}
if (username.length < 3) {
throw new Error("用户名至少3个字符");
}
if (password.length < 6) {
throw new Error("密码至少6个字符");
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
throw new Error("邮箱格式不正确");
}
const existingUser = await db.get(
"SELECT id FROM user WHERE username = ? OR email = ?",
[username, email]
);
if (existingUser) {
throw new Error("用户名或邮箱重复");
}
const salt = generateSalt();
const encryptedPassword = md5hash(password, salt);
const result = await db.run(
"INSERT INTO user (username, email, password, salt) VALUES (?, ?, ?, ?)",
[username, email, encryptedPassword, salt]
);
return {
success: true,
id: db.type === "mysql" ? result.insertId : result.lastInsertRowid,
username,
email,
message: "用户注册成功"
};
} catch (error) {
return { // 不要说前面throw偷懒了,这样还可以规避db操作中的问题
success: false,
error: error.message
};
}
}
static async login(username, password) {
try {
if (!username || !password) {
throw new Error("请提供用户名和密码");
}
const user = await db.get(
"SELECT * FROM user WHERE username = ? OR email = ?",
[username, username] // 用户可以输入邮箱来着,所以这样
);
if (!user) {
throw new Error("用户不存在");
}
const encryptedInputPassword = md5hash(password, user.salt);
if (encryptedInputPassword !== user.password) {
throw new Error("密码错误");
}
const token = jwt.sign(
{
id: user.id,
username: user.username,
email: user.email
},
jwtServerSecret,
{ expiresIn: "12h" }
);
return {
success: true,
id: user.id,
username: user.username,
email: user.email,
token,
message: "登录成功"
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
static verifyToken(req, res, next) {
// 用来验证JWT的middleware
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return res.status(401).json({
success: false,
error: "缺少令牌,访问拒绝"
});
}
const token = authHeader.split(" ")[1];
try {
const verified = jwt.verify(token, jwtServerSecret);
req.user = verified;
next();
} catch (error) {
res.status(400).json({
success: false,
error: "无效令牌,访问拒绝"
});
}
}
static async checkUsernameAvailable(username) {
// 其实在前面register的时候也有检查,不过单独查一遍也没事
try {
const user = await db.get(
"SELECT id FROM user WHERE username = ?",
[username]
);
return {
success: true,
available: !user
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
}
module.exports = Authenticate;