From 1cd705665eca4cf6a78f68b34f1c231a08cb96d8 Mon Sep 17 00:00:00 2001 From: tone <3341154833@qq.com> Date: Sat, 31 Aug 2024 22:52:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E7=AB=AF=E5=AE=8C=E6=88=90jwt?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Server/package.json | 2 + Server/pnpm-lock.yaml | 84 ++++++++++++++++++++++++++++++-- Server/src/APIs/Console/Login.ts | 50 +++++++++++++++++++ Server/src/Server/Server.ts | 3 ++ Server/src/ServerStdResponse.ts | 10 ++++ Server/src/config.ts | 6 ++- 6 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 Server/src/APIs/Console/Login.ts diff --git a/Server/package.json b/Server/package.json index 8cc4802..90ed791 100644 --- a/Server/package.json +++ b/Server/package.json @@ -13,7 +13,9 @@ "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.21", + "@types/jsonwebtoken": "^9.0.6", "@types/node": "^20.12.12", + "jsonwebtoken": "^9.0.2", "ts-node": "^10.9.2", "typescript": "^5.4.5" }, diff --git a/Server/pnpm-lock.yaml b/Server/pnpm-lock.yaml index 45f84e1..04e1088 100644 --- a/Server/pnpm-lock.yaml +++ b/Server/pnpm-lock.yaml @@ -34,9 +34,15 @@ devDependencies: '@types/express': specifier: ^4.17.21 version: 4.17.21 + '@types/jsonwebtoken': + specifier: ^9.0.6 + version: 9.0.6 '@types/node': specifier: ^20.12.12 version: 20.12.12 + jsonwebtoken: + specifier: ^9.0.2 + version: 9.0.2 ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) @@ -330,6 +336,12 @@ packages: resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} dev: true + /@types/jsonwebtoken@9.0.6: + resolution: {integrity: sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==} + dependencies: + '@types/node': 20.12.12 + dev: true + /@types/mime@1.3.5: resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} dev: true @@ -430,6 +442,10 @@ packages: - supports-color dev: false + /buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + dev: true + /bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -579,6 +595,12 @@ packages: engines: {node: '>=0.3.1'} dev: true + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + /ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: false @@ -801,14 +823,73 @@ packages: resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==} dev: false + /jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.6.3 + dev: true + + /jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: true + + /jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + dev: true + /lodash.defaults@4.2.0: resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} dev: false + /lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + dev: true + /lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} dev: false + /lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + dev: true + + /lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + dev: true + + /lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + dev: true + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: true + + /lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + dev: true + + /lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + dev: true + /long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} dev: false @@ -869,7 +950,6 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: false /mysql2@3.9.7: resolution: {integrity: sha512-KnJT8vYRcNAZv73uf9zpXqNbvBG7DJrs+1nACsjZP1HMJ1TgXEy8wnNilXAn/5i57JizXKtrUtwDB7HxT9DDpw==} @@ -970,7 +1050,6 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: false /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -980,7 +1059,6 @@ packages: resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} hasBin: true - dev: false /send@0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} diff --git a/Server/src/APIs/Console/Login.ts b/Server/src/APIs/Console/Login.ts new file mode 100644 index 0000000..3be2074 --- /dev/null +++ b/Server/src/APIs/Console/Login.ts @@ -0,0 +1,50 @@ +import { API } from "../../Plugs/API/API"; +import ServerStdResponse from "../../ServerStdResponse"; +import MySQLConnection from '../../Plugs/MySQLConnection' +import MountUserAgent from "../../Plugs/Middleware/MountUserAgent"; +import MountIP from "../../Plugs/Middleware/MountIP"; +import CheckCaptchaPassed from "../../Plugs/Middleware/CheckCaptchaPassed"; +import config from "../../config"; +import jwt from 'jsonwebtoken' +import crypto from 'crypto' + +// 登录 +class Login extends API { + constructor() { + super('POST', '/console/login', CheckCaptchaPassed, MountUserAgent, MountIP); + } + + public async onRequset(data: any, res: any) { + let { username, password, _ip, _userAgent } = data; + if (!username || !password) { + return res.json(ServerStdResponse.PARAMS_MISSING); + } + + // 检查用户是否存在 + let userInfoRes = await MySQLConnection.execute('SELECT * FROM user WHERE username = ?', [username]); + if(!userInfoRes){ + return res.json(ServerStdResponse.SERVER_ERROR); + } + if (userInfoRes.length != 1) { + return res.json(ServerStdResponse.USER.NOTFOUND); + } + userInfoRes = userInfoRes[0]; + // 检查密码是否正确 + if(crypto.createHash('sha256').update(`${userInfoRes.salt}${password}`).digest('hex') != userInfoRes.password){ + return res.json(ServerStdResponse.USER.PASSWORD_ERROR); + } + + // 准备jwtToken + const jwtPayload = { + uuid: userInfoRes.uuid, + loginTime: Date.now() + } + let jwtToken = jwt.sign(jwtPayload, config.jwt.secret, { expiresIn: config.jwt.expiresIn }); + + // 写入登录日志 + MySQLConnection.execute('INSERT INTO user_login_log (user_uuid, ip, user_agent, time) VALUES (?,?,?,?)', [userInfoRes.uuid, _ip, _userAgent, Date.now()]); + return res.json({ ...ServerStdResponse.OK, data: { token: jwtToken } }); + } +} + +export default Login; \ No newline at end of file diff --git a/Server/src/Server/Server.ts b/Server/src/Server/Server.ts index ca3f815..9ba3490 100644 --- a/Server/src/Server/Server.ts +++ b/Server/src/Server/Server.ts @@ -15,6 +15,7 @@ import BlogComment from "../APIs/BlogComment"; import GetBlogComment from "../APIs/GetBlogComment"; import GetCaptcha from "../APIs/GetCaptcha"; import CheckCaptcha from "../APIs/CheckCaptcha"; +import Login from "../APIs/Console/Login"; class Server { private logger = new Logger('Server'); @@ -37,6 +38,8 @@ class Server { this.apiLoader.add(GetCaptcha); this.apiLoader.add(CheckCaptcha); + this.apiLoader.add(Login); + this.apiLoader.start(config.apiPort); } } diff --git a/Server/src/ServerStdResponse.ts b/Server/src/ServerStdResponse.ts index 2c787a3..810d09c 100644 --- a/Server/src/ServerStdResponse.ts +++ b/Server/src/ServerStdResponse.ts @@ -42,6 +42,16 @@ const ServerStdResponse = { code: -5002, message: 'captcha is not right, please try again' } + }, + USER: { + NOTFOUND: { + code: -6000, + message: 'user is not found' + }, + PASSWORD_ERROR:{ + code: -6001, + message: 'user password is error' + } } } as const; diff --git a/Server/src/config.ts b/Server/src/config.ts index 02bf2f8..2cfcac8 100644 --- a/Server/src/config.ts +++ b/Server/src/config.ts @@ -13,8 +13,10 @@ const config = { password: '' // password: 'jhkdjhkjdhsIUTYURTU_f7EJZJ' }, - authToken: '17e50223f4a545ec9e36ebf08e2f71bb', - adminToken: '3a6f71412f9e48b9bbbd056aa7eb5467', + jwt: { + secret: '17e50223f4a545ec9e36ebf08e2f71bb', + expiresIn: '1d', + }, apiPort: 23500, } as const;