/* * @Author: HonorLee * @Version 1.0 * @LastUpdate 2018/6/19 * @License MIT */ import { RedisClientType } from '@redis/client'; import MD5 from 'md5' export default class Session{ public static setStorageType(type:'file'|'redis',instance:RedisClientType|undefined){ SessionManager._storageType = type; if(type=='redis') SessionManager._storageInstance = instance; } //Session实例 public sessionID:string; private _sessionKey:string; private _requestData:RequestData; constructor(requestData:RequestData,sessionID?:string|undefined){ this.sessionID = sessionID?sessionID:MD5(new Date().getTime()+''+Math.floor(Math.random()*9000+1000)); this._sessionKey = `session_${this.sessionID}`; this._requestData = requestData; if(!sessionID && this._requestData.res){ let sessionCookie = `SESSIONID=${this.sessionID};max-age=${7*24*60*60};path=/`; if(requestData.refer.host) sessionCookie += `;domain=${requestData.refer.host}`; this._requestData.res.setHeader('Set-Cookie',sessionCookie); } } async set(key:string,value:any|null){ if(!await SessionManager.check(this._sessionKey)){ this.set('sessionid',this.sessionID); this.setExpire(7*24*60*60); } return await SessionManager.set(this._sessionKey,key,value); } async setExpire(expire:number,autoRenew?:boolean){ return await SessionManager.setExpire(this._sessionKey,expire,autoRenew) } async get(key:string){ return await SessionManager.get(this._sessionKey,key); } async getAll(){ return await SessionManager.getAll(this._sessionKey); } async clear(){ return await SessionManager.clear(this._sessionKey); } } class SessionManager{ //全局存储控制 public static _storageType = 'file'; //默认以文件形式存储 public static _storageInstance:RedisClientType|undefined; public static async check(sessionKey:string){ if(SessionManager._storageType=='redis' && SessionManager._storageInstance){ const ret = await SessionManager._storageInstance.exists(sessionKey); if(ret==1) return true; return false; } } public static async set(sessionKey:string,key:string,value:any|null){ if(SessionManager._storageType=='redis' && SessionManager._storageInstance){ let ret; if(value==null){ ret= await SessionManager._storageInstance.hDel(sessionKey,key); }else{ ret= await SessionManager._storageInstance.hSet(sessionKey,key,value); } if(ret) return true else return false; }else{ } return true; } public static async setExpire(sessionKey:string,expire:number,autoRenew?:boolean){ if(SessionManager._storageType=='redis' && SessionManager._storageInstance){ const ret = await SessionManager._storageInstance?.expire(sessionKey,expire); if(!ret) return false; }else{ } return true; } public static async get(sessionKey:string,key:string){ let ret; if(SessionManager._storageType=='redis' && SessionManager._storageInstance){ ret = await SessionManager._storageInstance.hGet(sessionKey,key); }else{ } return ret; } public static async getAll(sessionKey:string){ let ret; if(SessionManager._storageType=='redis' && SessionManager._storageInstance){ ret = await SessionManager._storageInstance.hGetAll(sessionKey); }else{ } return true; } public static async clear(sessionKey:string){ let ret; if(SessionManager._storageType=='redis' && SessionManager._storageInstance){ ret = await SessionManager._storageInstance.del(sessionKey); }else{ } return ret; } } /** setWithSessionID:function(sessionID,key,value,callback){ callback = Manager.buildCallback(callback); if(!key || value==null) return callback.call(this,'Session key or value is empty',null); let _this = this; let session = {}; session.id = sessionID; session.data = {}; session.data[key] = value; session.expire = Config.SessionExpire*60; session.expireTime = new Date().getTime()+session.expire*1000; session.autoRenewExpire = Config.SessionExpire*60; Manager.set(session,function(err){ if(err) return callback.call(_this,'Session set err;',null); callback.call(_this,null,session); }); }, setExpireTime:function(sessionid,expire,autoRenewExpire,callback){ let _this = this; callback = Manager.buildCallback(callback); if(!sessionid) return callback.call(this,'Session id is empty',null); if(!expire) return callback.call(this,'Session expire must bigger than 0',null); Session.get(sessionid,function(err,data){ if(err || !data) return callback.call(this,'Session is gone',null); let session = data; session.expire = expire*60; autoRenewExpire = autoRenewExpire*1; if(autoRenewExpire>0) session.autoRenewExpire = autoRenewExpire*60; Manager.set(session,function(err){ if(err){ LOGGER.error(err); callback.call(_this,'Session set expire error',null); }else{ callback.call(_this,null,session); } }) }); }, update:function(sessionid,key,value,callback){ callback = Manager.buildCallback(callback); if(!sessionid || !key || value==null) return callback.call(this,'Session id,key or value is empty',null); let _this = this; Manager.get(sessionid,function(err,result){ let session; if(err || result == null){ session = {id:sessionid,data:{}}; }else{ session = result; } if(err || result == null || Config.Session.AutoRefresh){ session.expire = session.autoRenewExpire; session.expireTime = new Date().getTime()+session.expire*1000; } session.data[key] = value; Manager.set(session,function(err){ if(err) return callback.call(_this,'Session set error'); callback.call(_this,null,session) }); }); }, get:function(sessionid,callback){ callback = Manager.buildCallback(callback); if(!sessionid) return callback.call(this,'Session id is empty',null); let _this = this; Manager.get(sessionid,function(err,result){ callback.call(_this,null,result); }); }, getKeyValue:function(sessionid,key,callback){ callback = Manager.buildCallback(callback); if(!sessionid || !key) return callback.call(this,'Session id or key is empty',null); let _this = this; Session.get(sessionid,function(err,result){ if(err || !result) return callback.call(_this,null); callback.call(_this,null,result.data[key]); }); }, clear:function(sessionid){ if(!sessionid) return; Manager.clear(sessionid); }, instance:function(sessionID,callback){ return new Instance(sessionID,callback); } }; module.exports = Session; var Manager = { get:function(sessionid,callback){ let session; if(Config.Session.StoreType.toLowerCase()=='memcache' && Config.Database.Memcache.on && Memcache){ Memcache.get('session_'+sessionid,function(err,result){ if(err) return callback(err); session = result; callback(null,result); if(session && Config.Session.AutoRefresh){ session.expire = session.autoRenewExpire; session.expireTime = new Date().getTime()+session.expire*1000; Manager.set(session,null); } }); }else{ try{ session = JSON.parse(FILE.readFileSync(Core.Path.Session + '/' + sessionid,'UTF-8')); }catch(e){} if(session && session.expireTime){ if(new Date().getTime()>session.expireTime){ if(Config.Session.AutoRefresh){ session.expire = session.autoRenewExpire; session.expireTime = new Date().getTime()+session.expire*1000; Manager.set(session,null); }else{ session = null; Manager.clear(sessionid); } } } if(callback) callback(null,session); } }, set:function(session,callback){ if(Config.Session.StoreType.toLowerCase()=='memcache' && Config.Database.Memcache.on && Memcache){ Memcache.set('session_'+session.id,session,session.expire,function(err){ if(err){ Logger.error(err); if(callback) callback(err); return; } if(callback) callback(); }); }else{ FILE.writeFileSync(Core.Path.Session + '/' + session.id,JSON.stringify(session),'UTF-8'); if(callback) callback(); } }, clear:function(sessionid){ if(Config.Session.StoreType.toLowerCase()=='memcache' && Config.Database.Memcache.on && Memcache){ Memcache.del('session_'+sessionid); }else{ try{ FILE.rmdirSync(Core.Path.Session + '/' + sessionid); }catch(e){} } }, buildCallback:function(callback){ if(callback && typeof callback=='function') return callback; return function(){}; } } var Instance = function(sessionID,callback){ var _data; var _sessionID = sessionID; var _this = this; this.sessionID = _sessionID; this.get = function(key){ return _data[key]; } this.set = function(key,value){ _data[key] = value; Session.update(_sessionID,key,value); } this.setExpireTime = function(expire,autoRenewExpire){ Session.setExpireTime(_sessionID,expire,autoRenewExpire); } if(sessionID){ Session.get(sessionID,function(err,session){ if(err || !session){ Session.setWithSessionID(sessionID,'status',0,function(err,new_session){ _data = new_session.data; // _this.sessionID = new_session.id; if(callback) callback(sessionID,_this); }); }else{ _data = session.data; _this.sessionID = session.id; if(callback) callback(session.id,_this); } }); }else{ Session.set('status',0,function(err,new_session){ _data = new_session.data; _sessionID = new_session.id; _this.sessionID = new_session.id; if(callback) callback(new_session.id,_this); }); } return this; } **/