shaogen1995 hace 1 mes
padre
commit
ee80de97ca

+ 0 - 5
src/app.ts

@@ -9,8 +9,6 @@ import { getLocalIP } from './util/index.js';
 import { errorHandler } from './middleware/index.js';
 import proofZhong from './middleware/proof.js';
 
-import { clearAllFu } from './util/clearAll.js';
-
 const app = express();
 
 // 解析客户端请求
@@ -46,9 +44,6 @@ app.use('/api/v1', router);
 // 最后,注册错误处理中间件
 app.use(errorHandler);
 
-// 每晚12点定时清理
-clearAllFu();
-
 app.listen(8500, () => {
   console.log('Run http://localhost:8500');
   console.log(`Run http://${getLocalIP()}:8500`);

+ 1 - 3
src/controller/auditController.ts

@@ -2,9 +2,7 @@ import dayjs from 'dayjs';
 import { Audit, AuditFile } from '../model/index.js';
 import { generateCaptcha, ipLocResFu } from '../util/index.js';
 import resSend from '../util/resSend.js';
-import { isEnv, upStaticFileUrl } from '../config/config.default.js';
-import path from 'path';
-import { deleteFileSafely } from '../util/clearAll.js';
+import { isEnv } from '../config/config.default.js';
 
 //  需要做定时器处理,防止短时间多次发送
 let loginFlag: any = {};

+ 14 - 4
src/controller/userController.ts

@@ -4,7 +4,7 @@ import { Log, User } from '../model/index.js';
 import { getTokenFu } from '../middleware/jwt.js';
 import { passWordJia, passWordJie } from '../util/pass.js';
 import resSend from '../util/resSend.js';
-import { generateCaptcha, ipLocResFu } from '../util/index.js';
+import { dianNaoId, generateCaptcha } from '../util/index.js';
 
 // 登录模块 需要做定时器处理,防止短时间多次发送
 let loginFlag: any = {};
@@ -22,13 +22,21 @@ const loginTimeFu = (key: string) => {
 const user = {
   getCode: async (req: any, res: any) => {
     req.apiDescription = '用户模块-获取验证码';
-    const clientIp = ipLocResFu(req);
+    const clientIp = dianNaoId(req);
+
+    // console.log('--------', clientIp);
 
     const captcha = generateCaptcha();
     // 将验证码文本存入session(小写以便不区分大小写校验)
     const captchaTxt = captcha.text.toLowerCase();
     if (loginFlag[clientIp]) loginFlag[clientIp].loginFlagCode = captchaTxt;
-    else loginFlag[clientIp] = { loginFlagCode: captchaTxt };
+    else
+      loginFlag[clientIp] = {
+        loginFlagNum: 0,
+        loginFlagTime: 0,
+        loginFlagRef: null,
+        loginFlagCode: captchaTxt,
+      };
 
     // console.log('生成的验证码(开发调试用):', captchaTxt); // 调试时可查看
 
@@ -39,7 +47,7 @@ const user = {
   login: async (req: any, res: any) => {
     req.apiDescription = '用户模块-用户登录';
 
-    const clientIp = ipLocResFu(req);
+    const clientIp = dianNaoId(req);
     if (!loginFlag[clientIp]) {
       loginFlag[clientIp] = {
         loginFlagNum: 0,
@@ -49,6 +57,8 @@ const user = {
       };
     }
 
+    // console.log('asdasdas', loginFlag);
+
     if (loginFlag[clientIp].loginFlagNum >= 5) {
       if (loginFlag[clientIp].loginFlagRef) clearTimeout(loginFlag[clientIp].loginFlagRef);
 

+ 4 - 0
src/model/index.ts

@@ -13,6 +13,7 @@ import fileSchema from './fileModel.js';
 import zUserSchema from './zUserModel.js';
 import zLogSchema from './zLogModel.js';
 import zListSchema from './zlistModel.js';
+import { clearAllFu } from '../util/clearAll.js';
 
 const main = async () => {
   await mongoose.connect(mongodbUrl);
@@ -21,6 +22,9 @@ const main = async () => {
 main()
   .then(() => {
     console.log('链接成功');
+
+    // 每晚12点定时清理
+    clearAllFu();
   })
   .catch((err) => {
     console.log('链接错误', err);

+ 2 - 0
src/util/clearAll.ts

@@ -144,6 +144,8 @@ export async function deleteFileSafely(filePath: string) {
 }
 
 export const clearAllFu = () => {
+  console.log('----开启定时任务');
+
   // 每晚12点清理文件
   cron.schedule(
     '0 0 * * *',

+ 60 - 6
src/util/index.ts

@@ -40,13 +40,67 @@ export const generateCaptcha = () => {
   return res;
 };
 
-//3:------------  获取请求者ip 用来确定验证码是否正确
+// 生成电脑唯一id
+import crypto from 'crypto';
+
+export const dianNaoId = (req: any) => {
+  // 1. 首先使用原有逻辑获取IP地址
+  let clientIp = req.ip; // 如果使用了 Express 等框架,有时可以直接这样获取
+
+  // 优先从常见的代理头信息中获取
+  const forwardedHeader = req.headers['x-forwarded-for'];
+  const realIpHeader = req.headers['x-real-ip'];
+
+  if (forwardedHeader) {
+    // X-Forwarded-For 格式为 "client, proxy1, proxy2",第一个 IP 是真实客户端 IP
+    clientIp = forwardedHeader.split(',')[0].trim();
+  } else if (realIpHeader) {
+    // X-Real-IP 通常直接包含客户端的真实 IP
+    clientIp = realIpHeader;
+  } else {
+    // 如果没有代理头信息,则回退到连接信息(通常只在直接访问时有效)
+    let rawIp = req.socket.remoteAddress || req.connection.remoteAddress;
+    // 处理 IPv6 格式(如 "::ffff:192.168.1.1")
+    clientIp = rawIp && rawIp.replace(/^.*:/, '');
+  }
+
+  // 2. 收集其他可以区分设备的请求头信息
+  const userAgent = req.headers['user-agent'] || 'unknown';
+  const acceptLanguage = req.headers['accept-language'] || 'unknown';
+  const acceptEncoding = req.headers['accept-encoding'] || 'unknown';
+  const secCHUA = req.headers['sec-ch-ua'] || ''; // 客户端提示(较新的浏览器支持)
+  const secCHUAPlatform = req.headers['sec-ch-ua-platform'] || '';
+
+  // 3. 组合所有信息生成一个复合字符串
+  const compositeString = `${clientIp}-${userAgent}-${acceptLanguage}-${acceptEncoding}-${secCHUA}-${secCHUAPlatform}`;
+
+  // 4. 使用SHA-256哈希生成固定长度的设备指纹(更安全,冲突概率低)
+  const deviceFingerprint = crypto.createHash('sha256').update(compositeString).digest('hex');
+
+  return deviceFingerprint;
+};
+
+//3:------------  获取请求者ip
 export const ipLocResFu = (req: any) => {
-  // 获取IP,并处理可能的IPv6格式
-  let rawIp = req.socket.remoteAddress;
-  // 简单的处理,如果包含`::ffff:`则去除,否则直接使用
-  const clientIp = rawIp && rawIp.replace(/^.*:/, '');
-  // console.log('客户端IP:', clientIp);
+  let clientIp = req.ip; // 如果使用了 Express 等框架,有时可以直接这样获取
+
+  // 优先从常见的代理头信息中获取
+  const forwardedHeader = req.headers['x-forwarded-for'];
+  const realIpHeader = req.headers['x-real-ip'];
+
+  if (forwardedHeader) {
+    // X-Forwarded-For 格式为 "client, proxy1, proxy2",第一个 IP 是真实客户端 IP[6,7](@ref)
+    clientIp = forwardedHeader.split(',')[0].trim();
+  } else if (realIpHeader) {
+    // X-Real-IP 通常直接包含客户端的真实 IP[1,3](@ref)
+    clientIp = realIpHeader;
+  } else {
+    // 如果没有代理头信息,则回退到连接信息(通常只在直接访问时有效)
+    let rawIp = req.socket.remoteAddress || req.connection.remoteAddress;
+    // 处理 IPv6 格式(如 "::ffff:192.168.1.1")[2](@ref)
+    clientIp = rawIp && rawIp.replace(/^.*:/, '');
+  }
+
   return clientIp;
 };