chengjie 5 月之前
父節點
當前提交
d58c6c9d28
共有 2 個文件被更改,包括 123 次插入141 次删除
  1. 51 129
      src/api/web/webController.js
  2. 72 12
      src/util/stringClass.js

+ 51 - 129
src/api/web/webController.js

@@ -7,79 +7,7 @@ import _ from 'lodash';
7 7
 import { Encrypt, Decrypt } from '../../util/crypto/index.js';
8 8
 import axios from 'axios';
9 9
 import commonModel from '../../model/commonModel.js';
10
-
11
-// 验证IP地址格式是否有效
12
-function isValidIP(ip) {
13
-    if (!ip) return false;
14
-    // IPv4格式验证
15
-    const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
16
-    if (ipv4Regex.test(ip)) {
17
-        const parts = ip.split('.');
18
-        return parts.every(part => {
19
-            const num = parseInt(part, 10);
20
-            return num >= 0 && num <= 255;
21
-        });
22
-    }
23
-    // IPv6格式验证(简化版)
24
-    const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
25
-    return ipv6Regex.test(ip);
26
-}
27
-
28
-// 获取客户端真实IP地址的通用函数
29
-function getClientIP(ctx) {
30
-    // 检查所有可能的代理头
31
-    const proxyHeaders = [
32
-        'x-forwarded-for',
33
-        'x-real-ip',
34
-        'x-client-ip',
35
-        'x-forwarded',
36
-        'forwarded-for',
37
-        'x-cluster-client-ip',
38
-        'proxy-client-ip',
39
-        'cf-connecting-ip',    // Cloudflare
40
-        'true-client-ip',      // Akamai and Cloudflare
41
-        'fastly-client-ip',    // Fastly
42
-        'x-original-forwarded-for'
43
-    ];
44
-
45
-    let clientIP = null;
46
-
47
-    // 1. 首先检查所有代理头
48
-    for (const header of proxyHeaders) {
49
-        const value = ctx.request.headers[header];
50
-        if (value) {
51
-            // 处理可能的多个IP地址(取第一个,通常是最原始的客户端IP)
52
-            clientIP = value.split(',')[0].trim();
53
-            if (isValidIP(clientIP)) {
54
-                break;
55
-            }
56
-        }
57
-    }
58
-
59
-    // 2. 如果没有找到有效的代理头IP,尝试Koa的标准方法
60
-    if (!clientIP || !isValidIP(clientIP)) {
61
-        clientIP = ctx.ip || ctx.request.ip;
62
-    }
63
-
64
-    // 3. 如果还是没有,尝试socket
65
-    if (!clientIP || !isValidIP(clientIP)) {
66
-        clientIP = ctx.request.socket.remoteAddress;
67
-    }
68
-
69
-    // 处理IPv6格式
70
-    if (clientIP) {
71
-        // 处理IPv4映射的IPv6地址 (::ffff:127.0.0.1 格式)
72
-        if (clientIP.startsWith('::ffff:')) {
73
-            clientIP = clientIP.substring(7);
74
-        }
75
-        // 处理IPv6本地回环地址
76
-        else if (clientIP === '::1') {
77
-            clientIP = '127.0.0.1';
78
-        }
79
-    }
80
-
81
-    return clientIP || '0.0.0.0';
82
-}
10
+import { stringUtils } from '../../util/stringClass.js';
83 11
 
84 12
 //网站登录
85 13
 export async function WebLogin (ctx){
@@ -240,22 +168,10 @@ export async function WebLogout(ctx) {
240 168
 export async function Kylx365DBAdmin(ctx) {
241 169
     console.log("Kylx365DBAdmin");
242 170
 
243
-    const allowedIP = '192.168.1.100';      // 您的本地IP
244
-    const clientToken = ctx.req.headers['x-auth-token'];
245
-    
171
+    const IP = await commonModel.RunSql(null,"SELECT IPAddress FROM MiaoguoWXUsers WHERE UserID = 1;");
172
+    const allowedIP = IP[0].IPAddress;
246 173
     // 使用增强的IP获取函数
247
-    let clientIP = getClientIP(ctx);
248
-    
249
-    // 记录详细的IP信息用于调试
250
-    console.log('IP来源信息:', {
251
-        'x-forwarded-for': ctx.request.headers['x-forwarded-for'],
252
-        'x-real-ip': ctx.request.headers['x-real-ip'],
253
-        'ctx.ip': ctx.ip,
254
-        'socket.remoteAddress': ctx.request.socket.remoteAddress,
255
-        '最终使用的IP': clientIP,
256
-        '所有请求头': ctx.request.headers
257
-    });
258
-    
174
+    let clientIP = stringUtils.GetClientIP(ctx);
259 175
     console.log("clientIP:" + clientIP);
260 176
     let data = "";
261 177
     
@@ -289,51 +205,57 @@ export async function GetKylx365TableColumnByTable(ctx) {
289 205
  * @description 只允许执行SELECT查询语句,并对结果中的时间字段格式化和长文本截断
290 206
  */
291 207
 export async function RunKylx365DBSql(ctx) {
292
-    let param = {
293
-        SQL: ctx.request.body.sql || "",
294
-        IsCompleteField:ctx.request.body.IsCompleteField || false,
295
-    };
296
-    
208
+    const IP = await commonModel.RunSql(null,"SELECT IPAddress FROM MiaoguoWXUsers WHERE UserID = 1;");
209
+    const allowedIP = IP[0].IPAddress;
297 210
     // 使用增强的IP获取函数
298
-    let clientIP = getClientIP(ctx);
299
-    
300
-    console.log("客户端IP: " + clientIP);
301
-    console.log(param.SQL);
302
-    
303
-    // 获取第一个分号前的SQL语句
304
-    const firstStatement = param.SQL.split(';')[0].trim();
211
+    let clientIP = stringUtils.GetClientIP(ctx);
212
+    console.log("clientIP:" + clientIP);
305 213
     
306
-    // 只允许执行SELECT查询
307
-    if (!firstStatement.toUpperCase().startsWith('SELECT')) {
308
-        ctx.body = {"errcode": 10001, errmsg: "只允许执行SELECT查询语句"};
309
-        return;
310
-    }
214
+    if (clientIP === allowedIP || clientIP=="127.0.0.1") {
311 215
 
312
-    let result = await commonModel.RunSql(null, firstStatement);
313
-    console.log("记录数:" + result.length);
216
+        let param = {
217
+            SQL: ctx.request.body.sql || "",
218
+            IsCompleteField:ctx.request.body.IsCompleteField || false,
219
+        };
220
+        console.log(param.SQL);
314 221
     
315
-    // 处理查询结果
316
-    if (result && result.length > 0) {
317
-        result = result.map(item => {
318
-            const processedItem = {};
319
-            for (const [key, value] of Object.entries(item)) {
320
-                // 处理时间字段 - 仅处理Date对象或字段名包含日期时间关键词的
321
-                const isDateTimeField = key.toLowerCase().includes('time') || 
322
-                                      key.toLowerCase().includes('date') ||
323
-                                      key.toLowerCase().includes('timestamp');
324
-                if (value instanceof Date || (isDateTimeField && moment(value, moment.ISO_8601, true).isValid())) {
325
-                    processedItem[key] = moment(value).format('YYYY-MM-DD HH:mm:ss');
326
-                }
327
-                // 处理长文本字段
328
-                else if (!param.IsCompleteField && typeof value === 'string' && value.length > 100) {
329
-                    processedItem[key] = value.substring(0, 100) + '...';
330
-                } else {
331
-                    processedItem[key] = value;
222
+        // 获取第一个分号前的SQL语句
223
+        const firstStatement = param.SQL.split(';')[0].trim();
224
+        
225
+        // 只允许执行SELECT查询
226
+        if (!firstStatement.toUpperCase().startsWith('SELECT')) {
227
+            ctx.body = {"errcode": 10001, errmsg: "只允许执行SELECT查询语句"};
228
+            return;
229
+        }
230
+
231
+        let result = await commonModel.RunSql(null, firstStatement);
232
+        console.log("记录数:" + result.length);
233
+        
234
+        // 处理查询结果
235
+        if (result && result.length > 0) {
236
+            result = result.map(item => {
237
+                const processedItem = {};
238
+                for (const [key, value] of Object.entries(item)) {
239
+                    // 处理时间字段 - 仅处理Date对象或字段名包含日期时间关键词的
240
+                    const isDateTimeField = key.toLowerCase().includes('time') || 
241
+                                        key.toLowerCase().includes('date') ||
242
+                                        key.toLowerCase().includes('timestamp');
243
+                    if (value instanceof Date || (isDateTimeField && moment(value, moment.ISO_8601, true).isValid())) {
244
+                        processedItem[key] = moment(value).format('YYYY-MM-DD HH:mm:ss');
245
+                    }
246
+                    // 处理长文本字段
247
+                    else if (!param.IsCompleteField && typeof value === 'string' && value.length > 100) {
248
+                        processedItem[key] = value.substring(0, 100) + '...';
249
+                    } else {
250
+                        processedItem[key] = value;
251
+                    }
332 252
                 }
333
-            }
334
-            return processedItem;
335
-        });
336
-    }
253
+                return processedItem;
254
+            });
255
+        }
337 256
 
338
-    ctx.body = {"errcode": 10000, result: result};
257
+        ctx.body = {"errcode": 10000, result: result};
258
+    } else {
259
+        ctx.body = {"errcode": 10000, result: "There is an error in accessing the web page."};
260
+    }
339 261
 };

+ 72 - 12
src/util/stringClass.js

@@ -42,18 +42,7 @@ export const stringUtils = {
42 42
     },
43 43
     //判断是否是数字,true:是,false:不是
44 44
     IsNumber: (value) => /^\d+$/.test(value),
45
-    //得到IP地址
46
-    GetClientIp: (req) => {
47
-        let ip = req.headers['x-forwarded-for'] ||
48
-            req.connection.remoteAddress ||
49
-            req.socket.remoteAddress ||
50
-            req.connection.socket.remoteAddress;
51
-        ip = ip.replace("::ffff:", "");
52
-        if (ip === ":::1") {
53
-            ip = "127.0.0.1";
54
-        }
55
-        return ip;
56
-    },
45
+    
57 46
     //获取服务器IP地址
58 47
     GetServerIP: () => {
59 48
         const interfaces = os.networkInterfaces();
@@ -533,5 +522,76 @@ export const stringUtils = {
533 522
         }
534 523
         // 非数字或非数字字符串保持原样返回
535 524
         return input;
525
+    },
526
+    // 验证IP地址格式是否有效
527
+    IsValidIP: (ip) => {
528
+        if (!ip) return false;
529
+        // IPv4格式验证
530
+        const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
531
+        if (ipv4Regex.test(ip)) {
532
+            const parts = ip.split('.');
533
+            return parts.every(part => {
534
+                const num = parseInt(part, 10);
535
+                return num >= 0 && num <= 255;
536
+            });
537
+        }
538
+        // IPv6格式验证(简化版)
539
+        const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
540
+        return ipv6Regex.test(ip);
541
+    },
542
+    // 获取客户端真实IP地址的通用函数
543
+    GetClientIP: (ctx) => {
544
+        // 检查所有可能的代理头
545
+        const proxyHeaders = [
546
+            'x-forwarded-for',
547
+            'x-real-ip',
548
+            'x-client-ip',
549
+            'x-forwarded',
550
+            'forwarded-for',
551
+            'x-cluster-client-ip',
552
+            'proxy-client-ip',
553
+            'cf-connecting-ip',    // Cloudflare
554
+            'true-client-ip',      // Akamai and Cloudflare
555
+            'fastly-client-ip',    // Fastly
556
+            'x-original-forwarded-for'
557
+        ];
558
+
559
+        let clientIP = null;
560
+
561
+        // 1. 首先检查所有代理头
562
+        for (const header of proxyHeaders) {
563
+            const value = ctx.request.headers[header];
564
+            if (value) {
565
+                    // 处理可能的多个IP地址(取第一个,通常是最原始的客户端IP)
566
+                    clientIP = value.split(',')[0].trim();
567
+                    if (stringUtils.IsValidIP(clientIP)) {
568
+                        break;
569
+                    }
570
+                }
571
+            }
572
+
573
+            // 2. 如果没有找到有效的代理头IP,尝试Koa的标准方法
574
+            if (!clientIP || !stringUtils.IsValidIP(clientIP)) {
575
+                clientIP = ctx.ip || ctx.request.ip;
576
+            }
577
+
578
+            // 3. 如果还是没有,尝试socket
579
+            if (!clientIP || !stringUtils.IsValidIP(clientIP)) {
580
+                clientIP = ctx.request.socket.remoteAddress;
581
+            }
582
+
583
+        // 处理IPv6格式
584
+        if (clientIP) {
585
+            // 处理IPv4映射的IPv6地址 (::ffff:127.0.0.1 格式)
586
+            if (clientIP.startsWith('::ffff:')) {
587
+                clientIP = clientIP.substring(7);
588
+            }
589
+            // 处理IPv6本地回环地址
590
+            else if (clientIP === '::1') {
591
+                clientIP = '127.0.0.1';
592
+            }
593
+        }
594
+
595
+        return clientIP || '0.0.0.0';
536 596
     }
537 597
 }