短报文教学

This commit is contained in:
2026-03-27 17:57:07 +08:00
commit 4da5047bf2
27 changed files with 1073 additions and 0 deletions

110
app/core/base_controller.js Normal file
View File

@@ -0,0 +1,110 @@
const { Controller } = require('egg');
const sha256 = require("crypto-js/sha256");
const CryptoJS = require("crypto-js");
const KEY = CryptoJS.enc.Utf8.parse('BDQH');
class BaseController extends Controller {
shaForm = (body, salt) => {
return sha256(sha256(body).toString() + salt).toString();
}
encryptRequest = (body) => {
return CryptoJS.AES.encrypt(body, KEY, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}).toString();
}
decryptRequest = (body) => {
return CryptoJS.AES.decrypt(body, KEY, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}).toString(CryptoJS.enc.Utf8);
}
checkUid = async (ctx, uid) => {
const token = ctx.request.header.authorization;
const redis = ctx.app.redis;
let rdmcode;
if (!uid) {
const [buser, cuser] = await Promise.all([
redis.get('db0').get(token),
redis.get('db1').get(token),
]);
rdmcode = buser || cuser;
} else {
const redisType = {
"B": "db0",
"C": "db1"
};
const lastCode = uid[uid.length - 1];
rdmcode = await redis.get(redisType[lastCode]).get(token);
}
if (!rdmcode) {
return false;
}
return rdmcode;
};
setResponse = (ctx, code, msg, model, data = {}) => {
const modelType = {
"none": { code, msg },
"deconstruction": { code, msg, ...data },
"polymerization": { code, msg, data }
}
ctx.body = modelType[model];
}
// 黑名单管理器
banManager = async (redis, token) => {
// 基本元素
const now = new Date().getTime();
let reex = 1209600;
let tokenContainer = await redis.get('db4').get('tokenContainer');
let tokenCheck = await redis.get('db4').get(token);
let ex = await redis.get('db4').ttl(token);
tokenCheck = JSON.parse(tokenCheck);
// 判断存放教学接口 token 的容器是否存在,不存在则创建并设置过期时间
if (!tokenContainer == null) {
reex = await redis.get('db4').ttl('tokenContainer');
if (reex <= 600) {
reex = 1209600;
await redis.get('db4').set('tokenContainer', JSON.stringify(JSON.parse(tokenContainer)), 'EX', reex);
}
} else {
let createContainer = {};
createContainer[token] = { num: 1, firstTime: now };
await redis.get('db4').set('tokenContainer', JSON.stringify(createContainer), 'EX', reex);
}
tokenContainer = JSON.parse(tokenContainer);
if (tokenContainer !== null && tokenCheck !== null) {
// 黑名单回收器
for (let item in tokenContainer) {
if (tokenContainer[item].firstTime < now - 1000) {
delete tokenContainer[item];
}
}
// 黑名单释放器
if (tokenCheck.attacksMark && now - tokenCheck.banAt > 3600000) {
await redis.get('db4').set(token, JSON.stringify({ uid: tokenCheck.uid, attacksMark: false }), 'EX', ex);
}
// 黑名单检查器
if (!tokenContainer[token]) {
tokenContainer[token] = { num: 1, firstTime: now }
} else {
tokenContainer[token].num += 1;
if (tokenContainer[token].num > 10) {
delete tokenContainer[token];
// 黑名单标记器
await redis.get('db4').set(token, JSON.stringify({ uid: tokenCheck.uid, attacksMark: true, banAt: now }), 'EX', ex);
}
}
await redis.get('db4').set('tokenContainer', JSON.stringify(tokenContainer), 'EX', reex);
}
}
}
module.exports = BaseController;

85
app/core/base_service.js Normal file
View File

@@ -0,0 +1,85 @@
const { Service } = require('egg');
const sha256 = require("crypto-js/sha256");
const CryptoJS = require("crypto-js");
const KEY = CryptoJS.enc.Utf8.parse('BDQH');
class BaseService extends Service {
shaForm = (body, salt) => {
return sha256(sha256(body).toString() + salt).toString();
}
encryptRequest = (body) => {
return CryptoJS.AES.encrypt(body, KEY, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}).toString();
}
decryptRequest = (body) => {
return CryptoJS.AES.decrypt(body, KEY, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}).toString(CryptoJS.enc.Utf8);
}
// 随机盐生成函数
generateRandomString = () => {
const lowerCaseLetters = 'abcdefghijklmnopqrstuvwxyz';
const upperCaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const numbers = '0123456789';
let result = '';
// 生成5位随机小写字母
for (let i = 0; i < 5; i++) {
const randomIndex = Math.floor(Math.random() * lowerCaseLetters.length);
result += lowerCaseLetters[randomIndex];
}
// 生成5位随机大写字母
for (let i = 0; i < 5; i++) {
const randomIndex = Math.floor(Math.random() * upperCaseLetters.length);
result += upperCaseLetters[randomIndex];
}
// 生成2位随机数字
for (let i = 0; i < 2; i++) {
const randomIndex = Math.floor(Math.random() * numbers.length);
result += numbers[randomIndex];
}
// 打乱整个字符串
const characters = result.split('');
for (let i = characters.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[characters[i], characters[j]] = [characters[j], characters[i]];
}
return characters.join('');
}
// 教学接口 token 验证,验证 token 是否存在,是否在黑名单中
Verify = async (redis, teachingToken) => {
const token = await redis.get('db4').get(teachingToken);
if (!token) {
return 401;
} else if (JSON.parse(token).attacksMark) {
return 403;
}
return JSON.parse(token).uid;
}
shunt = (uid) => {
return uid[uid.length - 1];
}
isAllDigits = (str) => {
const regex = /^\d+$/;
return regex.test(str);
}
}
module.exports = BaseService;