mm_session 1.5.1 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/helper.js ADDED
@@ -0,0 +1,99 @@
1
+ const crypto = require('crypto');
2
+
3
+ /**
4
+ * 帮助类
5
+ */
6
+ class Helper {
7
+ /**
8
+ * 构造函数
9
+ */
10
+ constructor() {
11
+ }
12
+ }
13
+
14
+ /**
15
+ * AES编码字符串
16
+ * @param {string} text 输入文本
17
+ * @param {string} key 编码密钥
18
+ * @param {string} iv 初始化向量
19
+ * @returns {string} 编码后的字符串
20
+ */
21
+ Helper.prototype.aesEncode = function (text, key, iv) {
22
+ // 1. 创建cipher对象
23
+ const cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
24
+ // 2. 更新加密数据
25
+ let enc = cipher.update(text, 'utf8', 'hex');
26
+ // 3. 完成加密
27
+ enc += cipher.final('hex');
28
+ return enc;
29
+ };
30
+
31
+ /**
32
+ * AES解码字符串
33
+ * @param {string} text - 输入文本
34
+ * @param {string} key - 解码密钥
35
+ * @param {string} iv - 初始化向量
36
+ * @returns {string} 解码后的字符串
37
+ */
38
+ Helper.prototype.aesDecode = function (text, key, iv) {
39
+ // 1. 创建decipher对象
40
+ const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
41
+ // 2. 更新解密数据
42
+ let dec = decipher.update(text, 'hex', 'utf8');
43
+ // 3. 完成解密
44
+ dec += decipher.final('utf8');
45
+ return dec;
46
+ };
47
+
48
+
49
+ /**
50
+ * 生成session ID的密钥
51
+ * @param {string} user_agent 用户代理字符串
52
+ * @returns {string} 密钥
53
+ */
54
+ Helper.prototype._getSecret = function (user_agent = 'mm') {
55
+ // md5方法由mm_expand模块提供
56
+ return user_agent.md5().substring(0, 16);
57
+ };
58
+
59
+ /**
60
+ * 生成session ID
61
+ * @param {string} key 密钥
62
+ * @param {string} ip 客户端IP
63
+ * @param {string} user_agent 用户代理字符串
64
+ * @param {number} uuid_expire 过期时间(秒)
65
+ * @returns {string} session ID
66
+ */
67
+ Helper.prototype.genId = function (key, ip, user_agent = 'mm', uuid_expire = 604800) {
68
+ // 生成session ID的初始化向量
69
+ var iv = this._getSecret(user_agent);
70
+ var end_time = new Date().addSeconds(uuid_expire).stamp();
71
+ // 加密
72
+ var uuid = this.aesEncode(ip + '_' + end_time, key, iv);
73
+ return uuid;
74
+ };
75
+
76
+ /**
77
+ * 解析session ID
78
+ * @param {string} key 密钥
79
+ * @param {string} uuid session ID
80
+ * @param {string} user_agent 用户代理字符串
81
+ * @returns {object} 解析结果
82
+ */
83
+ Helper.prototype.parseId = function (key, uuid, user_agent = 'mm') {
84
+ // 生成session ID的初始化向量
85
+ var iv = this._getSecret(user_agent);
86
+ // 解密
87
+ var dec = this.aesDecode(uuid, key, iv);
88
+ // 解析IP和过期时间
89
+ var ip = dec.split('_')[0];
90
+ var end_time = dec.split('_')[1];
91
+ return {
92
+ ip,
93
+ end_time
94
+ };
95
+ };
96
+
97
+ module.exports = {
98
+ Helper
99
+ };
package/lib/session.js CHANGED
@@ -1,28 +1,67 @@
1
1
  const { Store } = require('./store.js');
2
+ const { Helper } = require('./helper.js');
3
+
4
+ if (!$.dict) {
5
+ // 增加字典
6
+ $.dict = {};
7
+ }
2
8
 
3
9
  /**
4
10
  * Session类
5
11
  */
6
12
  class Session {
13
+ /**
14
+ * 默认配置
15
+ */
16
+ static config = {
17
+ // 密钥
18
+ encrypt_key: $.config?.encrypt_key ? $.config.encrypt_key : 'mm'.md5().substring(0, 16),
19
+ // session存储在缓存中的key前缀,默认'mm:uuid'
20
+ key_prefix: $.dict.session_id || 'mm:uuid',
21
+ // session ID存储在cookie中的字段名,默认'mm:uuid'
22
+ cookie_token: $.dict.cookie_token || 'mm:uuid',
23
+ // HTTP请求头中用于传递session ID的字段名,默认'x-auth-token'
24
+ header_token: $.dict.header_token || 'x-auth-token',
25
+ // session ID过期时间,单位秒,默认7天
26
+ uuid_expire: $.dict.uuid_expire || 60 * 60 * 24 * 7,
27
+ // session过期时间,单位秒,默认2小时
28
+ max_age: 60 * 60 * 2,
29
+ // 过期token处理选项:'reject'(拒绝访问)或'allow'(允许访问缓存)
30
+ expired_handling: 'reject',
31
+ };
32
+
7
33
  /**
8
34
  * 构造函数
9
35
  * @param {object} config 配置选项
10
36
  */
11
37
  constructor(config = {}) {
12
- this.config = {
13
- key: $.dict.session_id || 'mm:uuid',
14
- ...config
15
- };
16
-
17
- this._store = new Store();
38
+ this.config = { ...Session.config };
39
+ this.setConfig(config);
40
+ this._init();
18
41
  }
19
42
  }
20
43
 
44
+ /**
45
+ * 设置session配置
46
+ * @param {object} config 配置选项
47
+ */
48
+ Session.prototype.setConfig = function (config) {
49
+ $.push(this.config, config);
50
+ };
51
+
52
+ /**
53
+ * 初始化session存储和助手
54
+ */
55
+ Session.prototype._init = function () {
56
+ this._store = new Store(this.config.key_prefix);
57
+ this._helper = new Helper();
58
+ };
59
+
21
60
  /**
22
61
  * 初始化session存储
23
62
  * @param {Store} store session存储实例
24
63
  */
25
- Session.prototype.init = function(store) {
64
+ Session.prototype.init = function (store) {
26
65
  if (store) {
27
66
  this._store = store;
28
67
  }
@@ -32,30 +71,79 @@ Session.prototype.init = function(store) {
32
71
  * 创建session中间件
33
72
  * @returns {Function} 中间件函数
34
73
  */
35
- Session.prototype.middleware = function() {
36
- return async (ctx, next) => {
37
- await this._handle(ctx, next);
74
+ Session.prototype.middleware = function () {
75
+ var self = this;
76
+
77
+ return async function (ctx, next) {
78
+ await self._handle(ctx, next);
38
79
  };
39
80
  };
40
81
 
41
82
  /**
42
- * 处理session逻辑
83
+ * 获取session对象
43
84
  * @param {object} ctx HTTP上下文
44
- * @param {Function} next 下一个中间件
85
+ * @returns {object} session对象
45
86
  */
46
- Session.prototype._handle = async function(ctx, next) {
47
- let uuid = this._get(ctx);
48
- let need_refresh = false;
87
+ Session.prototype.get = async function (ctx) {
88
+ // 获取协议头信息
89
+ let { ip, user_agent } = this._getHeaderInfo(ctx);
90
+ // 获取session ID
91
+ let session_id = this.getId(ctx);
92
+
93
+ // 验证session ID标识的有效性
94
+ if (session_id) {
95
+ let is_valid = await this._checkSessionId(session_id, ip, user_agent);
96
+ if (!is_valid) {
97
+ // token验证失败,返回null创建新session
98
+ session_id = null;
99
+ }
100
+ }
49
101
 
50
- ctx.session = await this._init(ctx, uuid, need_refresh);
102
+ // 获取session对象
103
+ let session = await this._get(session_id);
51
104
 
52
- this._add(ctx, need_refresh);
105
+ if (!session.uuid) {
106
+ session.uuid = this._genId(ip, user_agent);
107
+ }
108
+ // 创建session代理对象
109
+ ctx.session = this._create(session);
110
+ // 追加方法
111
+ this._addMethod(ctx);
112
+ return ctx.session;
113
+ };
53
114
 
115
+ /**
116
+ * 处理session逻辑
117
+ * @param {object} ctx HTTP上下文
118
+ * @param {Function} next 下一个中间件
119
+ */
120
+ Session.prototype._handle = async function (ctx, next) {
121
+ console.log(' - _handle方法开始执行');
122
+ let session_id = await this.get(ctx);
123
+
124
+ // 执行业务逻辑(包括登录/退出)
125
+ console.log(' - 执行next()之前');
54
126
  await next();
127
+ console.log(' - 执行next()之后');
55
128
 
56
- this._cleanup(ctx);
129
+ // 保存session(基于session是否被修改)
130
+ console.log(' - 准备调用save方法');
131
+ await this._save(ctx, session_id);
132
+ console.log(' - save方法执行完成');
133
+ };
57
134
 
58
- await this._save(ctx, uuid, need_refresh);
135
+ /**
136
+ * 获取协议头信息
137
+ * @param {object} ctx HTTP上下文
138
+ * @returns {object} session信息
139
+ */
140
+ Session.prototype._getHeaderInfo = function (ctx) {
141
+ let ip = ctx.ip || '127.0.0.1';
142
+ let user_agent = ctx.headers['user-agent'] || 'mm';
143
+ return {
144
+ ip,
145
+ user_agent
146
+ };
59
147
  };
60
148
 
61
149
  /**
@@ -63,59 +151,84 @@ Session.prototype._handle = async function(ctx, next) {
63
151
  * @param {object} ctx HTTP上下文
64
152
  * @returns {string} session ID
65
153
  */
66
- Session.prototype._get = function(ctx) {
67
- let uuid = ctx.cookies.get(this.config.key, this.config.config);
68
- if (!uuid) {
69
- uuid = ctx.headers[$.dict.token];
154
+ Session.prototype.getId = function (ctx) {
155
+ // 先尝试从cookie中获取session ID
156
+ let session_id = ctx.cookies.get(this.config.cookie_token, this.config.options);
157
+ if (!session_id) {
158
+ // 如果cookie中没有,尝试从header中获取
159
+ session_id = ctx.headers[this.config.header_token];
70
160
  }
71
- return uuid;
161
+ return session_id;
72
162
  };
73
163
 
74
164
  /**
75
- * 初始化session
76
- * @param {object} ctx HTTP上下文
77
- * @param {string} uuid session ID
78
- * @param {boolean} need_refresh 是否需要刷新
79
- * @returns {object} session对象
165
+ * 生成session ID
166
+ * @param {string} ip 客户端IP地址
167
+ * @param {string} user_agent 用户代理字符串
168
+ * @returns {string} 生成的session ID
80
169
  */
81
- Session.prototype._init = async function(ctx, uuid, need_refresh) {
82
- if (!uuid) {
83
- return this._new(ctx);
84
- }
170
+ Session.prototype._genId = function (ip, user_agent) {
171
+ return this._helper.genId(this.config.encrypt_key, ip, user_agent, this.config.uuid_expire);
172
+ };
85
173
 
86
- let session = await this._store.get(uuid);
87
- let result = { session, uuid, need_refresh };
174
+ /**
175
+ * 生成session ID
176
+ * @param {object} ctx HTTP上下文
177
+ * @returns {string} session ID
178
+ */
179
+ Session.prototype.genId = function (ctx) {
180
+ let { ip, user_agent } = this._getHeaderInfo(ctx);
181
+ return this._genId(ip, user_agent);
182
+ };
88
183
 
89
- if (session == null) {
90
- result.uuid = await this._store.getID(ctx);
91
- result.need_refresh = true;
184
+ /**
185
+ * 初始化session
186
+ *
187
+ * @param {string} session_id session ID
188
+ * @returns {object} session对象
189
+ */
190
+ Session.prototype._get = async function (session_id) {
191
+ let session;
192
+ if (session_id) {
193
+ var data = await this._store.get(session_id);
194
+ // 如果session不存在,创建新session
195
+ if (data) {
196
+ session = data;
197
+ // 现有session,设置标志位
198
+ session._is_new = false;
199
+ session._modified = false;
200
+ }
92
201
  }
93
-
94
- if (typeof session !== 'object' || session == null) {
95
- result.session = this._new(ctx);
202
+ if (!session) {
203
+ session = {
204
+ _is_new: true, // 新session标志
205
+ _modified: false // 修改标志
206
+ };
96
207
  }
97
-
98
- return result.session;
208
+ // 设置session的uuid属性
209
+ session.uuid = session_id;
210
+ return session;
99
211
  };
100
212
 
101
213
  /**
102
214
  * 创建新session
103
- * @param {object} ctx HTTP上下文
215
+ * @param {object} session session对象
104
216
  * @returns {Proxy} session代理对象
105
217
  */
106
- Session.prototype._new = function(ctx) {
107
- return new Proxy({}, {
108
- set: (obj, prop, value) => {
109
- const new_obj = { ...obj };
110
- new_obj[prop] = value;
111
-
112
- if (!new_obj.uuid) {
113
- this._store.getID(ctx).then((uuid) => {
114
- new_obj.uuid = uuid;
115
- });
218
+ Session.prototype._create = function (session) {
219
+ // 使用Proxy监听session修改
220
+ return new Proxy(session, {
221
+ set: function (target, property, value) {
222
+ // 内部属性不触发修改标记
223
+ if (property.startsWith('_')) {
224
+ Reflect.set(target, property, value);
225
+ return true;
116
226
  }
117
-
118
- Object.assign(obj, new_obj);
227
+
228
+ Reflect.set(target, property, value);
229
+ // 普通属性被设置时标记为已修改
230
+ Reflect.set(target, '_modified', true);
231
+ return true;
119
232
  }
120
233
  });
121
234
  };
@@ -123,22 +236,25 @@ Session.prototype._new = function(ctx) {
123
236
  /**
124
237
  * 添加session方法
125
238
  * @param {object} ctx HTTP上下文
126
- * @param {boolean} _need_refresh 是否需要刷新
127
239
  */
128
- Session.prototype._add = function(ctx, _need_refresh) {
240
+ Session.prototype._addMethod = function (ctx) {
129
241
  /**
130
242
  * 刷新session
131
243
  */
132
244
  ctx.session.refresh = () => {
133
245
  // 刷新标记在外部处理
246
+ ctx.session._modified = true;
134
247
  };
135
248
 
136
249
  /**
137
250
  * 获取session ID
138
251
  * @returns {string} session ID
139
252
  */
140
- ctx.session.getID = () => {
141
- return ctx.cookies.get(this.config.key, this.config.config);
253
+ ctx.session.getId = () => {
254
+ if (!ctx.session.uuid) {
255
+ ctx.session.uuid = this.genId(ctx);
256
+ }
257
+ return ctx.session.uuid;
142
258
  };
143
259
  };
144
260
 
@@ -146,98 +262,150 @@ Session.prototype._add = function(ctx, _need_refresh) {
146
262
  * 清理session
147
263
  * @param {object} ctx HTTP上下文
148
264
  */
149
- Session.prototype._cleanup = function(ctx) {
150
- if (ctx.session && 'refresh' in ctx.session) {
151
- delete ctx.session.refresh;
265
+ Session.prototype._cleanup = function (ctx) {
266
+ if (ctx.session) {
267
+ delete ctx.session._is_new;
268
+ delete ctx.session._modified;
152
269
  }
153
270
  };
154
271
 
155
272
  /**
156
- * 保存session
273
+ * 提取session数据(私有方法)
157
274
  * @param {object} ctx HTTP上下文
158
- * @param {string} uuid session ID
159
- * @param {boolean} need_refresh 是否需要刷新
275
+ * @returns {object} 提取的session数据
160
276
  */
161
- Session.prototype._save = async function(ctx, uuid, need_refresh) {
162
- if (!this._shouldSave(ctx, uuid, need_refresh)) {
163
- return;
164
- }
165
-
166
- if (this._shouldDestroySession(ctx, uuid)) {
167
- await this._destroySession(ctx, uuid);
168
- return;
169
- }
170
-
171
- let sid = await this._saveSession(ctx, uuid);
277
+ Session.prototype._extractSessionData = function (ctx) {
278
+ const session_to_save = {};
279
+
280
+ // 使用Reflect.ownKeys确保正确枚举Proxy对象的所有属性
281
+ const keys = Reflect.ownKeys(ctx.session);
282
+ console.log(' - 保存前session对象属性列表:', keys);
172
283
 
173
- if (this._shouldSetCookie(uuid, sid, need_refresh)) {
174
- this._setCookie(ctx, sid);
284
+ for (const key of keys) {
285
+ // 跳过Symbol类型的属性
286
+ if (typeof key === 'symbol') {
287
+ console.log(` - 跳过Symbol属性: ${key.toString()}`);
288
+ continue;
289
+ }
290
+
291
+ // 跳过函数属性和内部属性
292
+ if (typeof ctx.session[key] !== 'function' && !key.startsWith('_')) {
293
+ session_to_save[key] = ctx.session[key];
294
+ console.log(` - 保存属性到session_to_save: ${key} = ${ctx.session[key]}`);
295
+ } else {
296
+ console.log(` - 跳过属性: ${key} (类型: ${typeof ctx.session[key]})`);
297
+ }
175
298
  }
299
+
300
+ return session_to_save;
176
301
  };
177
302
 
178
303
  /**
179
- * 判断是否需要保存session
304
+ * 处理cookie设置(私有方法)
180
305
  * @param {object} ctx HTTP上下文
181
- * @param {string} _uuid session ID
182
- * @param {boolean} need_refresh 是否需要刷新
183
- * @returns {boolean} 是否需要保存
306
+ * @param {string} session_id session ID
184
307
  */
185
- Session.prototype._shouldSave = function(ctx, _uuid, need_refresh) {
186
- // 如果session为null,不需要保存
187
- if (ctx.session === null) {
188
- return false;
308
+ Session.prototype._handleCookie = async function (ctx, session_id) {
309
+ if (ctx.session.uuid !== session_id) {
310
+ // 如果session ID改变,需要更新cookie
311
+ await this._store.del(session_id);
312
+ this._setCookie(ctx, ctx.session.uuid);
189
313
  }
190
-
191
- // 如果需要刷新,总是保存
192
- if (need_refresh) {
193
- return true;
314
+ else if (ctx.session._is_new) {
315
+ // 新session,设置cookie
316
+ this._setCookie(ctx, ctx.session.uuid);
194
317
  }
195
-
196
- // 对于新session或修改过的session,需要保存
197
- // 这里简化逻辑,总是返回true以确保session被保存
198
- return true;
199
318
  };
200
319
 
201
320
  /**
202
- * 判断是否需要销毁session
321
+ * 保存session(私有方法)
203
322
  * @param {object} ctx HTTP上下文
204
- * @param {string} uuid session ID
205
- * @returns {boolean} 是否需要销毁
323
+ * @param {string} session_id session ID
324
+ * @returns {Promise<void>} 保存结果
206
325
  */
207
- Session.prototype._shouldDestroySession = function(ctx, uuid) {
208
- return uuid && !ctx.session;
326
+ Session.prototype._save = async function (ctx, session_id) {
327
+ // 如果session不存在,直接删除session
328
+ if (!ctx.session) {
329
+ await this._delSession(ctx, session_id);
330
+ return;
331
+ }
332
+
333
+ console.log(' - save方法: 检查session._modified标志:', ctx.session._modified);
334
+
335
+ // 如果session被修改过,需要保存
336
+ if (ctx.session._modified) {
337
+ await this._handleCookie(ctx, session_id);
338
+
339
+ // 提取session数据
340
+ const session_to_save = this._extractSessionData(ctx);
341
+
342
+ console.log(' - 保存前的session_to_save对象:', session_to_save);
343
+
344
+ // 保存内部属性(_is_new和_modified)
345
+ if (ctx.session._is_new !== undefined) {
346
+ session_to_save._is_new = ctx.session._is_new;
347
+ }
348
+ if (ctx.session._modified !== undefined) {
349
+ session_to_save._modified = ctx.session._modified;
350
+ }
351
+
352
+ console.log(' - 保存内部属性后的session_to_save对象:', session_to_save);
353
+
354
+ // 清理session
355
+ this._cleanup(ctx);
356
+
357
+ console.log(' - 清理session后的session_to_save对象:', session_to_save);
358
+
359
+ // 保存session到存储
360
+ return await this._store.set(ctx.session.uuid, session_to_save, this.config.max_age || 7200);
361
+ }
209
362
  };
210
363
 
211
364
  /**
212
- * 销毁session
365
+ * 保存session(公开方法)
213
366
  * @param {object} ctx HTTP上下文
214
- * @param {string} uuid session ID
367
+ * @param {string|object} session_id_or_obj session ID或session对象
368
+ * @returns {Promise<void>} 保存结果
215
369
  */
216
- Session.prototype._destroySession = async function(ctx, uuid) {
217
- await this._store.destroy(uuid, ctx);
218
- ctx.cookies.set(this.config.key, null);
370
+ Session.prototype.save = async function (ctx, session_id_or_obj) {
371
+ let session_id;
372
+
373
+ if (typeof session_id_or_obj === 'string') {
374
+ // 如果传入的是session ID字符串
375
+ session_id = session_id_or_obj;
376
+ } else if (session_id_or_obj && typeof session_id_or_obj.getId === 'function') {
377
+ // 如果传入的是session对象
378
+ session_id = session_id_or_obj.getId();
379
+ } else {
380
+ // 如果传入的是undefined或null,尝试从ctx.session获取
381
+ if (ctx.session && ctx.session.getId) {
382
+ session_id = ctx.session.getId();
383
+ } else {
384
+ throw new TypeError('无效的session参数');
385
+ }
386
+ }
387
+
388
+ return await this._save(ctx, session_id);
219
389
  };
220
390
 
221
391
  /**
222
- * 保存session到存储
392
+ * 销毁session
223
393
  * @param {object} ctx HTTP上下文
224
- * @param {string} uuid session ID
225
- * @returns {string} 新的session ID
394
+ * @param {string} session_id session ID
226
395
  */
227
- Session.prototype._saveSession = async function(ctx, uuid) {
228
- let o = { ...this.config.config, uuid: ctx.session.uuid || uuid};
229
- return await this._store.set(ctx.session, o, ctx);
396
+ Session.prototype._delSession = async function (ctx, session_id) {
397
+ ctx.cookies.set(this.config.cookie_token, null);
398
+ this._store.del(session_id).catch();
230
399
  };
231
400
 
232
401
  /**
233
402
  * 判断是否需要设置cookie
234
- * @param {string} uuid 原session ID
403
+ * @param {string} session_id 原session ID
235
404
  * @param {string} sid 新session ID
236
- * @param {boolean} need_refresh 是否需要刷新
237
405
  * @returns {boolean} 是否需要设置cookie
238
406
  */
239
- Session.prototype._shouldSetCookie = function(uuid, sid, need_refresh) {
240
- return !uuid || uuid !== sid || need_refresh;
407
+ Session.prototype._shouldSetCookie = function (session_id, sid) {
408
+ return !session_id || session_id !== sid;
241
409
  };
242
410
 
243
411
  /**
@@ -245,15 +413,62 @@ Session.prototype._shouldSetCookie = function(uuid, sid, need_refresh) {
245
413
  * @param {object} ctx HTTP上下文
246
414
  * @param {string} sid session ID
247
415
  */
248
- Session.prototype._setCookie = function(ctx, sid) {
249
- let cg = { ...this.config.config};
416
+ Session.prototype._setCookie = function (ctx, sid) {
417
+ let cg = { ...this.config.config };
250
418
  if (cg.max_age) {
251
419
  cg.maxAge = cg.max_age * 1000;
252
420
  delete cg.max_age;
253
421
  }
254
- ctx.cookies.set(this.config.key, sid, cg);
422
+ ctx.cookies.set(this.config.cookie_token, sid, cg);
255
423
  };
256
424
 
257
- module.exports = {
258
- Session
425
+ /**
426
+ * 验证token时效性
427
+ * @param {number} end_time token过期时间戳
428
+ * @returns {boolean} 是否过期
429
+ */
430
+ Session.prototype._verifyExpiration = async function (end_time) {
431
+ var current_time = Date.parse(new Date()) / 1000;
432
+ return current_time > end_time;
259
433
  };
434
+
435
+ /**
436
+ * 完整的token验证流程
437
+ * @param {string} session_id session ID
438
+ * @param {string} client_ip 客户端IP
439
+ * @param {string} client_ua 客户端UA字符串
440
+ * @returns {boolean} 是否验证通过
441
+ */
442
+ Session.prototype._checkSessionId = async function (session_id, client_ip, client_ua) {
443
+ try {
444
+ // 解码session_id
445
+ var data = this._helper.aesDecode(session_id,
446
+ this.config.encrypt_key, this._helper._getSecret(client_ua));
447
+ if (!data) return false;
448
+ let { ip, end_time } = data;
449
+ // 验证IP
450
+ if (ip !== client_ip) return false;
451
+
452
+ // 验证时效性
453
+ var is_expired = await this._verifyExpiration(end_time);
454
+ if (is_expired) {
455
+ if (this.config.expired_handling !== 'allow') {
456
+ return false;
457
+ }
458
+ }
459
+
460
+ // 所有验证通过
461
+ return true;
462
+ } catch (err) {
463
+ $.log.debug('Session ID验证错误:', err);
464
+ return false;
465
+ }
466
+ };
467
+
468
+ module.exports = {
469
+ Session,
470
+ session: function (options) {
471
+ let sess = new Session(options);
472
+ return sess.middleware();
473
+ }
474
+ };