diff options
Diffstat (limited to 'server/resty/session')
-rw-r--r-- | server/resty/session/ciphers/aes.lua | 113 | ||||
-rw-r--r-- | server/resty/session/ciphers/none.lua | 15 | ||||
-rw-r--r-- | server/resty/session/compressors/none.lua | 15 | ||||
-rw-r--r-- | server/resty/session/compressors/zlib.lua | 43 | ||||
-rw-r--r-- | server/resty/session/encoders/base16.lua | 29 | ||||
-rw-r--r-- | server/resty/session/encoders/base64.lua | 39 | ||||
-rw-r--r-- | server/resty/session/encoders/hex.lua | 1 | ||||
-rw-r--r-- | server/resty/session/hmac/sha1.lua | 1 | ||||
-rw-r--r-- | server/resty/session/identifiers/random.lua | 13 | ||||
-rw-r--r-- | server/resty/session/serializers/json.lua | 6 | ||||
-rw-r--r-- | server/resty/session/storage/cookie.lua | 7 | ||||
-rw-r--r-- | server/resty/session/storage/dshm.lua | 163 | ||||
-rw-r--r-- | server/resty/session/storage/memcache.lua | 303 | ||||
-rw-r--r-- | server/resty/session/storage/memcached.lua | 1 | ||||
-rw-r--r-- | server/resty/session/storage/redis.lua | 478 | ||||
-rw-r--r-- | server/resty/session/storage/shm.lua | 125 | ||||
-rw-r--r-- | server/resty/session/strategies/default.lua | 232 | ||||
-rw-r--r-- | server/resty/session/strategies/regenerate.lua | 43 |
18 files changed, 0 insertions, 1627 deletions
diff --git a/server/resty/session/ciphers/aes.lua b/server/resty/session/ciphers/aes.lua deleted file mode 100644 index 9a088ad..0000000 --- a/server/resty/session/ciphers/aes.lua +++ /dev/null @@ -1,113 +0,0 @@ -local aes = require "resty.aes" - -local setmetatable = setmetatable -local tonumber = tonumber -local ceil = math.ceil -local var = ngx.var -local sub = string.sub -local rep = string.rep - -local HASHES = aes.hash - -local CIPHER_MODES = { - ecb = "ecb", - cbc = "cbc", - cfb1 = "cfb1", - cfb8 = "cfb8", - cfb128 = "cfb128", - ofb = "ofb", - ctr = "ctr", - gcm = "gcm", -} - -local CIPHER_SIZES = { - [128] = 128, - [192] = 192, - [256] = 256, -} - -local defaults = { - size = CIPHER_SIZES[tonumber(var.session_aes_size, 10)] or 256, - mode = CIPHER_MODES[var.session_aes_mode] or "cbc", - hash = HASHES[var.session_aes_hash] or HASHES.sha512, - rounds = tonumber(var.session_aes_rounds, 10) or 1, -} - -local function adjust_salt(salt) - if not salt then - return nil - end - - local z = #salt - if z < 8 then - return sub(rep(salt, ceil(8 / z)), 1, 8) - end - if z > 8 then - return sub(salt, 1, 8) - end - - return salt -end - -local function get_cipher(self, key, salt) - local mode = aes.cipher(self.size, self.mode) - if not mode then - return nil, "invalid cipher mode " .. self.mode .. "(" .. self.size .. ")" - end - - return aes:new(key, adjust_salt(salt), mode, self.hash, self.rounds) -end - -local cipher = {} - -cipher.__index = cipher - -function cipher.new(session) - local config = session.aes or defaults - return setmetatable({ - size = CIPHER_SIZES[tonumber(config.size, 10)] or defaults.size, - mode = CIPHER_MODES[config.mode] or defaults.mode, - hash = HASHES[config.hash] or defaults.hash, - rounds = tonumber(config.rounds, 10) or defaults.rounds, - }, cipher) -end - -function cipher:encrypt(data, key, salt, _) - local cip, err = get_cipher(self, key, salt) - if not cip then - return nil, err or "unable to aes encrypt data" - end - - local encrypted_data - encrypted_data, err = cip:encrypt(data) - if not encrypted_data then - return nil, err or "aes encryption failed" - end - - if self.mode == "gcm" then - return encrypted_data[1], nil, encrypted_data[2] - end - - return encrypted_data -end - -function cipher:decrypt(data, key, salt, _, tag) - local cip, err = get_cipher(self, key, salt) - if not cip then - return nil, err or "unable to aes decrypt data" - end - - local decrypted_data - decrypted_data, err = cip:decrypt(data, tag) - if not decrypted_data then - return nil, err or "aes decryption failed" - end - - if self.mode == "gcm" then - return decrypted_data, nil, tag - end - - return decrypted_data -end - -return cipher diff --git a/server/resty/session/ciphers/none.lua b/server/resty/session/ciphers/none.lua deleted file mode 100644 index b29bb88..0000000 --- a/server/resty/session/ciphers/none.lua +++ /dev/null @@ -1,15 +0,0 @@ -local cipher = {} - -function cipher.new() - return cipher -end - -function cipher.encrypt(_, data, _, _) - return data -end - -function cipher.decrypt(_, data, _, _, _) - return data -end - -return cipher diff --git a/server/resty/session/compressors/none.lua b/server/resty/session/compressors/none.lua deleted file mode 100644 index 3d14a5c..0000000 --- a/server/resty/session/compressors/none.lua +++ /dev/null @@ -1,15 +0,0 @@ -local compressor = {} - -function compressor.new() - return compressor -end - -function compressor.compress(_, data) - return data -end - -function compressor.decompress(_, data) - return data -end - -return compressor diff --git a/server/resty/session/compressors/zlib.lua b/server/resty/session/compressors/zlib.lua deleted file mode 100644 index 1d23be0..0000000 --- a/server/resty/session/compressors/zlib.lua +++ /dev/null @@ -1,43 +0,0 @@ -local zlib = require "ffi-zlib" -local sio = require "pl.stringio" - -local concat = table.concat - -local function gzip(func, input) - local stream = sio.open(input) - local output = {} - local n = 0 - - local ok, err = func(function(size) - return stream:read(size) - end, function(data) - n = n + 1 - output[n] = data - end, 8192) - - if not ok then - return nil, err - end - - if n == 0 then - return "" - end - - return concat(output, nil, 1, n) -end - -local compressor = {} - -function compressor.new() - return compressor -end - -function compressor.compress(_, data) - return gzip(zlib.deflateGzip, data) -end - -function compressor.decompress(_, data) - return gzip(zlib.inflateGzip, data) -end - -return compressor diff --git a/server/resty/session/encoders/base16.lua b/server/resty/session/encoders/base16.lua deleted file mode 100644 index 552f50e..0000000 --- a/server/resty/session/encoders/base16.lua +++ /dev/null @@ -1,29 +0,0 @@ -local to_hex = require "resty.string".to_hex - -local tonumber = tonumber -local gsub = string.gsub -local char = string.char - -local function chr(c) - return char(tonumber(c, 16) or 0) -end - -local encoder = {} - -function encoder.encode(value) - if not value then - return nil, "unable to base16 encode value" - end - - return to_hex(value) -end - -function encoder.decode(value) - if not value then - return nil, "unable to base16 decode value" - end - - return (gsub(value, "..", chr)) -end - -return encoder diff --git a/server/resty/session/encoders/base64.lua b/server/resty/session/encoders/base64.lua deleted file mode 100644 index ddaf4e8..0000000 --- a/server/resty/session/encoders/base64.lua +++ /dev/null @@ -1,39 +0,0 @@ -local encode_base64 = ngx.encode_base64 -local decode_base64 = ngx.decode_base64 - -local gsub = string.gsub - -local ENCODE_CHARS = { - ["+"] = "-", - ["/"] = "_", -} - -local DECODE_CHARS = { - ["-"] = "+", - ["_"] = "/", -} - -local encoder = {} - -function encoder.encode(value) - if not value then - return nil, "unable to base64 encode value" - end - - local encoded = encode_base64(value, true) - if not encoded then - return nil, "unable to base64 encode value" - end - - return gsub(encoded, "[+/]", ENCODE_CHARS) -end - -function encoder.decode(value) - if not value then - return nil, "unable to base64 decode value" - end - - return decode_base64((gsub(value, "[-_]", DECODE_CHARS))) -end - -return encoder diff --git a/server/resty/session/encoders/hex.lua b/server/resty/session/encoders/hex.lua deleted file mode 100644 index 1b94a5a..0000000 --- a/server/resty/session/encoders/hex.lua +++ /dev/null @@ -1 +0,0 @@ -return require "resty.session.encoders.base16"
\ No newline at end of file diff --git a/server/resty/session/hmac/sha1.lua b/server/resty/session/hmac/sha1.lua deleted file mode 100644 index 1753412..0000000 --- a/server/resty/session/hmac/sha1.lua +++ /dev/null @@ -1 +0,0 @@ -return ngx.hmac_sha1 diff --git a/server/resty/session/identifiers/random.lua b/server/resty/session/identifiers/random.lua deleted file mode 100644 index a2f9739..0000000 --- a/server/resty/session/identifiers/random.lua +++ /dev/null @@ -1,13 +0,0 @@ -local tonumber = tonumber -local random = require "resty.random".bytes -local var = ngx.var - -local defaults = { - length = tonumber(var.session_random_length, 10) or 16 -} - -return function(session) - local config = session.random or defaults - local length = tonumber(config.length, 10) or defaults.length - return random(length, true) or random(length) -end diff --git a/server/resty/session/serializers/json.lua b/server/resty/session/serializers/json.lua deleted file mode 100644 index 960c4d8..0000000 --- a/server/resty/session/serializers/json.lua +++ /dev/null @@ -1,6 +0,0 @@ -local json = require "cjson.safe" - -return { - serialize = json.encode, - deserialize = json.decode, -} diff --git a/server/resty/session/storage/cookie.lua b/server/resty/session/storage/cookie.lua deleted file mode 100644 index 95e26d1..0000000 --- a/server/resty/session/storage/cookie.lua +++ /dev/null @@ -1,7 +0,0 @@ -local storage = {} - -function storage.new() - return storage -end - -return storage diff --git a/server/resty/session/storage/dshm.lua b/server/resty/session/storage/dshm.lua deleted file mode 100644 index e6d887f..0000000 --- a/server/resty/session/storage/dshm.lua +++ /dev/null @@ -1,163 +0,0 @@ -local dshm = require "resty.dshm" - -local setmetatable = setmetatable -local tonumber = tonumber -local concat = table.concat -local var = ngx.var - -local defaults = { - region = var.session_dshm_region or "sessions", - connect_timeout = tonumber(var.session_dshm_connect_timeout, 10), - read_timeout = tonumber(var.session_dshm_read_timeout, 10), - send_timeout = tonumber(var.session_dshm_send_timeout, 10), - host = var.session_dshm_host or "127.0.0.1", - port = tonumber(var.session_dshm_port, 10) or 4321, - pool = { - name = var.session_dshm_pool_name, - size = tonumber(var.session_dshm_pool_size, 10) or 100, - timeout = tonumber(var.session_dshm_pool_timeout, 10) or 1000, - backlog = tonumber(var.session_dshm_pool_backlog, 10), - }, -} - -local storage = {} - -storage.__index = storage - -function storage.new(session) - local config = session.dshm or defaults - local pool = config.pool or defaults.pool - - local connect_timeout = tonumber(config.connect_timeout, 10) or defaults.connect_timeout - - local store = dshm:new() - if store.set_timeouts then - local send_timeout = tonumber(config.send_timeout, 10) or defaults.send_timeout - local read_timeout = tonumber(config.read_timeout, 10) or defaults.read_timeout - - if connect_timeout then - if send_timeout and read_timeout then - store:set_timeouts(connect_timeout, send_timeout, read_timeout) - else - store:set_timeout(connect_timeout) - end - end - - elseif store.set_timeout and connect_timeout then - store:set_timeout(connect_timeout) - end - - - local self = { - store = store, - encoder = session.encoder, - region = config.region or defaults.region, - host = config.host or defaults.host, - port = tonumber(config.port, 10) or defaults.port, - pool_timeout = tonumber(pool.timeout, 10) or defaults.pool.timeout, - connect_opts = { - pool = pool.name or defaults.pool.name, - pool_size = tonumber(pool.size, 10) or defaults.pool.size, - backlog = tonumber(pool.backlog, 10) or defaults.pool.backlog, - }, - } - - return setmetatable(self, storage) -end - -function storage:connect() - return self.store:connect(self.host, self.port, self.connect_opts) -end - -function storage:set_keepalive() - return self.store:set_keepalive(self.pool_timeout) -end - -function storage:key(id) - return concat({ self.region, id }, "::") -end - -function storage:set(key, ttl, data) - local ok, err = self:connect() - if not ok then - return nil, err - end - - data, err = self.encoder.encode(data) - - if not data then - self:set_keepalive() - return nil, err - end - - ok, err = self.store:set(key, data, ttl) - - self:set_keepalive() - - return ok, err -end - -function storage:get(key) - local ok, err = self:connect() - if not ok then - return nil, err - end - - local data - data, err = self.store:get(key) - if data then - data, err = self.encoder.decode(data) - end - - self:set_keepalive() - - return data, err -end - -function storage:delete(key) - local ok, err = self:connect() - if not ok then - return nil, err - end - - ok, err = self.store:delete(key) - - self:set_keepalive() - - return ok, err -end - -function storage:touch(key, ttl) - local ok, err = self:connect() - if not ok then - return nil, err - end - - ok, err = self.store:touch(key, ttl) - - self:set_keepalive() - - return ok, err -end - -function storage:open(id) - local key = self:key(id) - return self:get(key) -end - -function storage:save(id, ttl, data) - local key = self:key(id) - return self:set(key, ttl, data) -end - -function storage:destroy(id) - local key = self:key(id) - return self:delete(key) -end - -function storage:ttl(id, ttl) - local key = self:key(id) - return self:touch(key, ttl) -end - -return storage diff --git a/server/resty/session/storage/memcache.lua b/server/resty/session/storage/memcache.lua deleted file mode 100644 index da44ba7..0000000 --- a/server/resty/session/storage/memcache.lua +++ /dev/null @@ -1,303 +0,0 @@ -local memcached = require "resty.memcached" -local setmetatable = setmetatable -local tonumber = tonumber -local concat = table.concat -local sleep = ngx.sleep -local null = ngx.null -local var = ngx.var - -local function enabled(value) - if value == nil then - return nil - end - - return value == true - or value == "1" - or value == "true" - or value == "on" -end - -local function ifnil(value, default) - if value == nil then - return default - end - - return enabled(value) -end - -local defaults = { - prefix = var.session_memcache_prefix or "sessions", - socket = var.session_memcache_socket, - host = var.session_memcache_host or "127.0.0.1", - uselocking = enabled(var.session_memcache_uselocking or true), - connect_timeout = tonumber(var.session_memcache_connect_timeout, 10), - read_timeout = tonumber(var.session_memcache_read_timeout, 10), - send_timeout = tonumber(var.session_memcache_send_timeout, 10), - port = tonumber(var.session_memcache_port, 10) or 11211, - spinlockwait = tonumber(var.session_memcache_spinlockwait, 10) or 150, - maxlockwait = tonumber(var.session_memcache_maxlockwait, 10) or 30, - pool = { - name = var.session_memcache_pool_name, - timeout = tonumber(var.session_memcache_pool_timeout, 10), - size = tonumber(var.session_memcache_pool_size, 10), - backlog = tonumber(var.session_memcache_pool_backlog, 10), - }, -} - -local storage = {} - -storage.__index = storage - -function storage.new(session) - local config = session.memcache or defaults - local pool = config.pool or defaults.pool - local locking = ifnil(config.uselocking, defaults.uselocking) - - local connect_timeout = tonumber(config.connect_timeout, 10) or defaults.connect_timeout - - local memcache = memcached:new() - if memcache.set_timeouts then - local send_timeout = tonumber(config.send_timeout, 10) or defaults.send_timeout - local read_timeout = tonumber(config.read_timeout, 10) or defaults.read_timeout - - if connect_timeout then - if send_timeout and read_timeout then - memcache:set_timeouts(connect_timeout, send_timeout, read_timeout) - else - memcache:set_timeout(connect_timeout) - end - end - - elseif memcache.set_timeout and connect_timeout then - memcache:set_timeout(connect_timeout) - end - - local self = { - memcache = memcache, - prefix = config.prefix or defaults.prefix, - uselocking = locking, - spinlockwait = tonumber(config.spinlockwait, 10) or defaults.spinlockwait, - maxlockwait = tonumber(config.maxlockwait, 10) or defaults.maxlockwait, - pool_timeout = tonumber(pool.timeout, 10) or defaults.pool.timeout, - connect_opts = { - pool = pool.name or defaults.pool.name, - pool_size = tonumber(pool.size, 10) or defaults.pool.size, - backlog = tonumber(pool.backlog, 10) or defaults.pool.backlog, - }, - } - - local socket = config.socket or defaults.socket - if socket and socket ~= "" then - self.socket = socket - else - self.host = config.host or defaults.host - self.port = config.port or defaults.port - end - - return setmetatable(self, storage) -end - -function storage:connect() - local socket = self.socket - if socket then - return self.memcache:connect(socket, self.connect_opts) - end - return self.memcache:connect(self.host, self.port, self.connect_opts) -end - -function storage:set_keepalive() - return self.memcache:set_keepalive(self.pool_timeout) -end - -function storage:key(id) - return concat({ self.prefix, id }, ":" ) -end - -function storage:lock(key) - if not self.uselocking or self.locked then - return true - end - - if not self.token then - self.token = var.request_id - end - - local lock_key = concat({ key, "lock" }, "." ) - local lock_ttl = self.maxlockwait + 1 - local attempts = (1000 / self.spinlockwait) * self.maxlockwait - local waittime = self.spinlockwait / 1000 - - for _ = 1, attempts do - local ok = self.memcache:add(lock_key, self.token, lock_ttl) - if ok then - self.locked = true - return true - end - - sleep(waittime) - end - - return false, "unable to acquire a session lock" -end - -function storage:unlock(key) - if not self.uselocking or not self.locked then - return true - end - - local lock_key = concat({ key, "lock" }, "." ) - local token = self:get(lock_key) - - if token == self.token then - self.memcache:delete(lock_key) - self.locked = nil - end -end - -function storage:get(key) - local data, err = self.memcache:get(key) - if not data then - return nil, err - end - - if data == null then - return nil - end - - return data -end - -function storage:set(key, data, ttl) - return self.memcache:set(key, data, ttl) -end - -function storage:expire(key, ttl) - return self.memcache:touch(key, ttl) -end - -function storage:delete(key) - return self.memcache:delete(key) -end - -function storage:open(id, keep_lock) - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - ok, err = self:lock(key) - if not ok then - self:set_keepalive() - return nil, err - end - - local data - data, err = self:get(key) - - if err or not data or not keep_lock then - self:unlock(key) - end - - self:set_keepalive() - - return data, err -end - -function storage:start(id) - if not self.uselocking or not self.locked then - return true - end - - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - ok, err = self:lock(key) - - self:set_keepalive() - - return ok, err -end - -function storage:save(id, ttl, data, close) - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - ok, err = self:set(key, data, ttl) - - if close then - self:unlock(key) - end - - self:set_keepalive() - - if not ok then - return nil, err - end - - return true -end - -function storage:close(id) - if not self.uselocking or not self.locked then - return true - end - - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - self:unlock(key) - self:set_keepalive() - - return true -end - -function storage:destroy(id) - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - ok, err = self:delete(key) - - self:unlock(key) - self:set_keepalive() - - return ok, err -end - -function storage:ttl(id, ttl, close) - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - ok, err = self:expire(key, ttl) - - if close then - self:unlock(key) - end - - self:set_keepalive() - - return ok, err -end - -return storage diff --git a/server/resty/session/storage/memcached.lua b/server/resty/session/storage/memcached.lua deleted file mode 100644 index 0ecc508..0000000 --- a/server/resty/session/storage/memcached.lua +++ /dev/null @@ -1 +0,0 @@ -return require "resty.session.storage.memcache" diff --git a/server/resty/session/storage/redis.lua b/server/resty/session/storage/redis.lua deleted file mode 100644 index 3de0472..0000000 --- a/server/resty/session/storage/redis.lua +++ /dev/null @@ -1,478 +0,0 @@ -local setmetatable = setmetatable -local tonumber = tonumber -local type = type -local reverse = string.reverse -local gmatch = string.gmatch -local find = string.find -local byte = string.byte -local sub = string.sub -local concat = table.concat -local sleep = ngx.sleep -local null = ngx.null -local var = ngx.var - -local LB = byte("[") -local RB = byte("]") - -local function parse_cluster_nodes(nodes) - if not nodes or nodes == "" then - return nil - end - - if type(nodes) == "table" then - return nodes - end - - local addrs - local i - for node in gmatch(nodes, "%S+") do - local ip = node - local port = 6379 - local pos = find(reverse(ip), ":", 2, true) - if pos then - local p = tonumber(sub(ip, -pos + 1), 10) - if p >= 1 and p <= 65535 then - local addr = sub(ip, 1, -pos - 1) - if find(addr, ":", 1, true) then - if byte(addr, -1) == RB then - ip = addr - port = p - end - - else - ip = addr - port = p - end - end - end - - if byte(ip, 1, 1) == LB then - ip = sub(ip, 2) - end - - if byte(ip, -1) == RB then - ip = sub(ip, 1, -2) - end - - if not addrs then - i = 1 - addrs = {{ - ip = ip, - port = port, - }} - else - i = i + 1 - addrs[i] = { - ip = ip, - port = port, - } - end - end - - if not i then - return - end - - return addrs -end - -local redis_single = require "resty.redis" -local redis_cluster -do - local pcall = pcall - local require = require - local ok - ok, redis_cluster = pcall(require, "resty.rediscluster") - if not ok then - ok, redis_cluster = pcall(require, "rediscluster") - if not ok then - redis_cluster = nil - end - end -end - -local UNLOCK = [[ -if redis.call("GET", KEYS[1]) == ARGV[1] then - return redis.call("DEL", KEYS[1]) -else - return 0 -end -]] - -local function enabled(value) - if value == nil then return nil end - return value == true or (value == "1" or value == "true" or value == "on") -end - -local function ifnil(value, default) - if value == nil then - return default - end - - return enabled(value) -end - -local defaults = { - prefix = var.session_redis_prefix or "sessions", - socket = var.session_redis_socket, - host = var.session_redis_host or "127.0.0.1", - username = var.session_redis_username, - password = var.session_redis_password or var.session_redis_auth, - server_name = var.session_redis_server_name, - ssl = enabled(var.session_redis_ssl) or false, - ssl_verify = enabled(var.session_redis_ssl_verify) or false, - uselocking = enabled(var.session_redis_uselocking or true), - port = tonumber(var.session_redis_port, 10) or 6379, - database = tonumber(var.session_redis_database, 10) or 0, - connect_timeout = tonumber(var.session_redis_connect_timeout, 10), - read_timeout = tonumber(var.session_redis_read_timeout, 10), - send_timeout = tonumber(var.session_redis_send_timeout, 10), - spinlockwait = tonumber(var.session_redis_spinlockwait, 10) or 150, - maxlockwait = tonumber(var.session_redis_maxlockwait, 10) or 30, - pool = { - name = var.session_redis_pool_name, - timeout = tonumber(var.session_redis_pool_timeout, 10), - size = tonumber(var.session_redis_pool_size, 10), - backlog = tonumber(var.session_redis_pool_backlog, 10), - }, -} - - -if redis_cluster then - defaults.cluster = { - name = var.session_redis_cluster_name, - dict = var.session_redis_cluster_dict, - maxredirections = tonumber(var.session_redis_cluster_maxredirections, 10), - nodes = parse_cluster_nodes(var.session_redis_cluster_nodes), - } -end - -local storage = {} - -storage.__index = storage - -function storage.new(session) - local config = session.redis or defaults - local pool = config.pool or defaults.pool - local cluster = config.cluster or defaults.cluster - local locking = ifnil(config.uselocking, defaults.uselocking) - - local self = { - prefix = config.prefix or defaults.prefix, - uselocking = locking, - spinlockwait = tonumber(config.spinlockwait, 10) or defaults.spinlockwait, - maxlockwait = tonumber(config.maxlockwait, 10) or defaults.maxlockwait, - } - - local username = config.username or defaults.username - if username == "" then - username = nil - end - local password = config.password or config.auth or defaults.password - if password == "" then - password = nil - end - - local connect_timeout = tonumber(config.connect_timeout, 10) or defaults.connect_timeout - - local cluster_nodes - if redis_cluster then - cluster_nodes = parse_cluster_nodes(cluster.nodes or defaults.cluster.nodes) - end - - local connect_opts = { - pool = pool.name or defaults.pool.name, - pool_size = tonumber(pool.size, 10) or defaults.pool.size, - backlog = tonumber(pool.backlog, 10) or defaults.pool.backlog, - server_name = config.server_name or defaults.server_name, - ssl = ifnil(config.ssl, defaults.ssl), - ssl_verify = ifnil(config.ssl_verify, defaults.ssl_verify), - } - - if cluster_nodes then - self.redis = redis_cluster:new({ - name = cluster.name or defaults.cluster.name, - dict_name = cluster.dict or defaults.cluster.dict, - username = var.session_redis_username, - password = var.session_redis_password or defaults.password, - connection_timout = connect_timeout, -- typo in library - connection_timeout = connect_timeout, - keepalive_timeout = tonumber(pool.timeout, 10) or defaults.pool.timeout, - keepalive_cons = tonumber(pool.size, 10) or defaults.pool.size, - max_redirection = tonumber(cluster.maxredirections, 10) or defaults.cluster.maxredirections, - serv_list = cluster_nodes, - connect_opts = connect_opts, - }) - self.cluster = true - - else - local redis = redis_single:new() - - if redis.set_timeouts then - local send_timeout = tonumber(config.send_timeout, 10) or defaults.send_timeout - local read_timeout = tonumber(config.read_timeout, 10) or defaults.read_timeout - - if connect_timeout then - if send_timeout and read_timeout then - redis:set_timeouts(connect_timeout, send_timeout, read_timeout) - else - redis:set_timeout(connect_timeout) - end - end - - elseif redis.set_timeout and connect_timeout then - redis:set_timeout(connect_timeout) - end - - self.redis = redis - self.username = username - self.password = password - self.database = tonumber(config.database, 10) or defaults.database - self.pool_timeout = tonumber(pool.timeout, 10) or defaults.pool.timeout - self.connect_opts = connect_opts - - local socket = config.socket or defaults.socket - if socket and socket ~= "" then - self.socket = socket - else - self.host = config.host or defaults.host - self.port = config.port or defaults.port - end - end - - return setmetatable(self, storage) -end - -function storage:connect() - if self.cluster then - return true -- cluster handles this on its own - end - - local ok, err - if self.socket then - ok, err = self.redis:connect(self.socket, self.connect_opts) - else - ok, err = self.redis:connect(self.host, self.port, self.connect_opts) - end - - if not ok then - return nil, err - end - - if self.password and self.redis:get_reused_times() == 0 then - -- usernames are supported only on Redis 6+, so use new AUTH form only when absolutely necessary - if self.username then - ok, err = self.redis:auth(self.username, self.password) - else - ok, err = self.redis:auth(self.password) - end - if not ok then - self.redis:close() - return nil, err - end - end - - if self.database ~= 0 then - ok, err = self.redis:select(self.database) - if not ok then - self.redis:close() - end - end - - return ok, err -end - -function storage:set_keepalive() - if self.cluster then - return true -- cluster handles this on its own - end - - return self.redis:set_keepalive(self.pool_timeout) -end - -function storage:key(id) - return concat({ self.prefix, id }, ":" ) -end - -function storage:lock(key) - if not self.uselocking or self.locked then - return true - end - - if not self.token then - self.token = var.request_id - end - - local lock_key = concat({ key, "lock" }, "." ) - local lock_ttl = self.maxlockwait + 1 - local attempts = (1000 / self.spinlockwait) * self.maxlockwait - local waittime = self.spinlockwait / 1000 - - for _ = 1, attempts do - local ok = self.redis:set(lock_key, self.token, "EX", lock_ttl, "NX") - if ok ~= null then - self.locked = true - return true - end - - sleep(waittime) - end - - return false, "unable to acquire a session lock" -end - -function storage:unlock(key) - if not self.uselocking or not self.locked then - return - end - - local lock_key = concat({ key, "lock" }, "." ) - - self.redis:eval(UNLOCK, 1, lock_key, self.token) - self.locked = nil -end - -function storage:get(key) - local data, err = self.redis:get(key) - if not data then - return nil, err - end - - if data == null then - return nil - end - - return data -end - -function storage:set(key, data, lifetime) - return self.redis:setex(key, lifetime, data) -end - -function storage:expire(key, lifetime) - return self.redis:expire(key, lifetime) -end - -function storage:delete(key) - return self.redis:del(key) -end - -function storage:open(id, keep_lock) - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - ok, err = self:lock(key) - if not ok then - self:set_keepalive() - return nil, err - end - - local data - data, err = self:get(key) - - if err or not data or not keep_lock then - self:unlock(key) - end - self:set_keepalive() - - return data, err -end - -function storage:start(id) - if not self.uselocking or not self.locked then - return true - end - - local ok, err = self:connect() - if not ok then - return nil, err - end - - ok, err = self:lock(self:key(id)) - - self:set_keepalive() - - return ok, err -end - -function storage:save(id, ttl, data, close) - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - ok, err = self:set(key, data, ttl) - - if close then - self:unlock(key) - end - - self:set_keepalive() - - if not ok then - return nil, err - end - - return true -end - -function storage:close(id) - if not self.uselocking or not self.locked then - return true - end - - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - self:unlock(key) - self:set_keepalive() - - return true -end - -function storage:destroy(id) - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - ok, err = self:delete(key) - - self:unlock(key) - self:set_keepalive() - - return ok, err -end - -function storage:ttl(id, ttl, close) - local ok, err = self:connect() - if not ok then - return nil, err - end - - local key = self:key(id) - - ok, err = self:expire(key, ttl) - - if close then - self:unlock(key) - end - - self:set_keepalive() - - return ok, err -end - -return storage diff --git a/server/resty/session/storage/shm.lua b/server/resty/session/storage/shm.lua deleted file mode 100644 index 6f81435..0000000 --- a/server/resty/session/storage/shm.lua +++ /dev/null @@ -1,125 +0,0 @@ -local lock = require "resty.lock" - -local setmetatable = setmetatable -local tonumber = tonumber -local concat = table.concat -local var = ngx.var -local shared = ngx.shared - -local function enabled(value) - if value == nil then return nil end - return value == true or (value == "1" or value == "true" or value == "on") -end - -local function ifnil(value, default) - if value == nil then - return default - end - - return enabled(value) -end - -local defaults = { - store = var.session_shm_store or "sessions", - uselocking = enabled(var.session_shm_uselocking or true), - lock = { - exptime = tonumber(var.session_shm_lock_exptime, 10) or 30, - timeout = tonumber(var.session_shm_lock_timeout, 10) or 5, - step = tonumber(var.session_shm_lock_step, 10) or 0.001, - ratio = tonumber(var.session_shm_lock_ratio, 10) or 2, - max_step = tonumber(var.session_shm_lock_max_step, 10) or 0.5, - } -} - -local storage = {} - -storage.__index = storage - -function storage.new(session) - local config = session.shm or defaults - local store = config.store or defaults.store - local locking = ifnil(config.uselocking, defaults.uselocking) - - local self = { - store = shared[store], - uselocking = locking, - } - - if locking then - local lock_opts = config.lock or defaults.lock - local opts = { - exptime = tonumber(lock_opts.exptime, 10) or defaults.exptime, - timeout = tonumber(lock_opts.timeout, 10) or defaults.timeout, - step = tonumber(lock_opts.step, 10) or defaults.step, - ratio = tonumber(lock_opts.ratio, 10) or defaults.ratio, - max_step = tonumber(lock_opts.max_step, 10) or defaults.max_step, - } - self.lock = lock:new(store, opts) - end - - return setmetatable(self, storage) -end - -function storage:open(id, keep_lock) - if self.uselocking then - local ok, err = self.lock:lock(concat{ id, ".lock" }) - if not ok then - return nil, err - end - end - - local data, err = self.store:get(id) - - if self.uselocking and (err or not data or not keep_lock) then - self.lock:unlock() - end - - return data, err -end - -function storage:start(id) - if self.uselocking then - return self.lock:lock(concat{ id, ".lock" }) - end - - return true -end - -function storage:save(id, ttl, data, close) - local ok, err = self.store:set(id, data, ttl) - if close and self.uselocking then - self.lock:unlock() - end - - return ok, err -end - -function storage:close() - if self.uselocking then - self.lock:unlock() - end - - return true -end - -function storage:destroy(id) - self.store:delete(id) - - if self.uselocking then - self.lock:unlock() - end - - return true -end - -function storage:ttl(id, lifetime, close) - local ok, err = self.store:expire(id, lifetime) - - if close and self.uselocking then - self.lock:unlock() - end - - return ok, err -end - -return storage diff --git a/server/resty/session/strategies/default.lua b/server/resty/session/strategies/default.lua deleted file mode 100644 index a43ef5a..0000000 --- a/server/resty/session/strategies/default.lua +++ /dev/null @@ -1,232 +0,0 @@ -local type = type -local concat = table.concat - -local strategy = {} - -function strategy.load(session, cookie, key, keep_lock) - local storage = session.storage - local id = cookie.id - local id_encoded = session.encoder.encode(id) - - local data, err, tag - if storage.open then - data, err = storage:open(id_encoded, keep_lock) - if not data then - return nil, err or "cookie data was not found" - end - - else - data = cookie.data - end - - local expires = cookie.expires - local usebefore = cookie.usebefore - local hash = cookie.hash - - if not key then - key = concat{ id, expires, usebefore } - end - - local hkey = session.hmac(session.secret, key) - - data, err, tag = session.cipher:decrypt(data, hkey, id, session.key, hash) - if not data then - if storage.close then - storage:close(id_encoded) - end - - return nil, err or "unable to decrypt data" - end - - if tag then - if tag ~= hash then - if storage.close then - storage:close(id_encoded) - end - - return nil, "cookie has invalid tag" - end - - else - local input = concat{ key, data, session.key } - if session.hmac(hkey, input) ~= hash then - if storage.close then - storage:close(id_encoded) - end - - return nil, "cookie has invalid signature" - end - end - - data, err = session.compressor:decompress(data) - if not data then - if storage.close then - storage:close(id_encoded) - end - - return nil, err or "unable to decompress data" - end - - data, err = session.serializer.deserialize(data) - if not data then - if storage.close then - storage:close(id_encoded) - end - - return nil, err or "unable to deserialize data" - end - - session.id = id - session.expires = expires - session.usebefore = usebefore - session.data = type(data) == "table" and data or {} - session.present = true - - return true -end - -function strategy.open(session, cookie, keep_lock) - return strategy.load(session, cookie, nil, keep_lock) -end - -function strategy.start(session) - local storage = session.storage - if not storage.start then - return true - end - - local id_encoded = session.encoder.encode(session.id) - - local ok, err = storage:start(id_encoded) - if not ok then - return nil, err or "unable to start session" - end - - return true -end - -function strategy.modify(session, action, close, key) - local id = session.id - local id_encoded = session.encoder.encode(id) - local storage = session.storage - local expires = session.expires - local usebefore = session.usebefore - local ttl = expires - session.now - - if ttl <= 0 then - if storage.close then - storage:close(id_encoded) - end - - return nil, "session is already expired" - end - - if not key then - key = concat{ id, expires, usebefore } - end - - local data, err = session.serializer.serialize(session.data) - if not data then - if close and storage.close then - storage:close(id_encoded) - end - - return nil, err or "unable to serialize data" - end - - data, err = session.compressor:compress(data) - if not data then - if close and storage.close then - storage:close(id_encoded) - end - - return nil, err or "unable to compress data" - end - - local hkey = session.hmac(session.secret, key) - - local encrypted_data, tag - encrypted_data, err, tag = session.cipher:encrypt(data, hkey, id, session.key) - if not encrypted_data then - if close and storage.close then - storage:close(id_encoded) - end - - return nil, err - end - - local hash - if tag then - hash = tag - else - -- it would be better to calculate signature from encrypted_data, - -- but this is kept for backward compatibility - hash = session.hmac(hkey, concat{ key, data, session.key }) - end - - if action == "save" and storage.save then - local ok - ok, err = storage:save(id_encoded, ttl, encrypted_data, close) - if not ok then - return nil, err - end - elseif close and storage.close then - local ok - ok, err = storage:close(id_encoded) - if not ok then - return nil, err - end - end - - if usebefore then - expires = expires .. ":" .. usebefore - end - - hash = session.encoder.encode(hash) - - local cookie - if storage.save then - cookie = concat({ id_encoded, expires, hash }, "|") - else - local encoded_data = session.encoder.encode(encrypted_data) - cookie = concat({ id_encoded, expires, encoded_data, hash }, "|") - end - - return cookie -end - -function strategy.touch(session, close) - return strategy.modify(session, "touch", close) -end - -function strategy.save(session, close) - return strategy.modify(session, "save", close) -end - -function strategy.destroy(session) - local id = session.id - if id then - local storage = session.storage - if storage.destroy then - return storage:destroy(session.encoder.encode(id)) - elseif storage.close then - return storage:close(session.encoder.encode(id)) - end - end - - return true -end - -function strategy.close(session) - local id = session.id - if id then - local storage = session.storage - if storage.close then - return storage:close(session.encoder.encode(id)) - end - end - - return true -end - -return strategy diff --git a/server/resty/session/strategies/regenerate.lua b/server/resty/session/strategies/regenerate.lua deleted file mode 100644 index f2a97dd..0000000 --- a/server/resty/session/strategies/regenerate.lua +++ /dev/null @@ -1,43 +0,0 @@ -local default = require "resty.session.strategies.default" - -local concat = table.concat - -local strategy = { - regenerate = true, - start = default.start, - destroy = default.destroy, - close = default.close, -} - -local function key(source) - if source.usebefore then - return concat{ source.id, source.usebefore } - end - - return source.id -end - -function strategy.open(session, cookie, keep_lock) - return default.load(session, cookie, key(cookie), keep_lock) -end - -function strategy.touch(session, close) - return default.modify(session, "touch", close, key(session)) -end - -function strategy.save(session, close) - if session.present then - local storage = session.storage - if storage.ttl then - storage:ttl(session.encoder.encode(session.id), session.cookie.discard, true) - elseif storage.close then - storage:close(session.encoder.encode(session.id)) - end - - session.id = session:identifier() - end - - return default.modify(session, "save", close, key(session)) -end - -return strategy |