Skip to content

Commit 75acdc3

Browse files
committed
Release 2.12.
1 parent 02a3b11 commit 75acdc3

File tree

5 files changed

+136
-55
lines changed

5 files changed

+136
-55
lines changed

Changes.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22

33
All notable changes to `lua-resty-session` will be documented in this file.
44

5+
## [2.12] - 2016-11-21
6+
### Added
7+
- Implemented pluggable session identifier generators.
8+
- Implemented random session idenfier generator.
9+
10+
### Changed
11+
- Now checks if headers were already sent before trying to set the
12+
cookie headers.
13+
- SSL session identifier is not checked by default anymore.
14+
- Lua session.identifier.length changed to session.random.length.
15+
- Nginx $session_identifier_length changed to $session_random_length.
16+
17+
## [2.11] - 2016-09-30
18+
### Changed
19+
- Just another OPM release to correct the name.
20+
521
## [2.10] - 2016-09-29
622
### Added
723
- Support for the official OpenResty package manager (opm).

README.md

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ http {
6161

6262
## Roadmap
6363

64-
* Add support for session id generator plugins (maybe you don't want to use random data, and want UUID or maybe some kind of database identifier instead).
6564
* Add support for different schemes:
6665
* Encrypt-and-MAC: The ciphertext is generated by encrypting the plaintext and then appending a MAC of the plaintext.
6766
* MAC-then-encrypt: The ciphertext is generated by appending a MAC to the plaintext and then encrypting everything.
@@ -475,6 +474,51 @@ To configure session to use your adapter, you can do so with Nginx configuration
475474
set $session_encoder base64;
476475
```
477476

477+
## Pluggable Session Identifier Ganerators
478+
479+
With version 2.12 we started to support pluggable session identifier generators in `lua-resty-session`.
480+
Right now we support only one type of generator, and that is:
481+
482+
* `random`
483+
484+
If you want to write your own session identifier generator, you need to implement one function:
485+
486+
* `string function(config)`
487+
488+
(the config is actually a session instance =
489+
490+
You have to place your generator inside `resty.session.identifiers` for auto-loader to work.
491+
492+
To configure session to use your generator, you can do so with Nginx configuration (or in Lua code):
493+
494+
```nginx
495+
set $session_identifier_generator random;
496+
```
497+
498+
#### Random Sesssion Identifier Generator
499+
500+
Random generator uses `lua-resty-string`'s (an OpenResty core library) OpenSSL based cryptographically
501+
safe random generator.
502+
503+
Random generator can be selected with configuration:
504+
505+
```nginx
506+
set $session_identifier random;
507+
```
508+
509+
Additionally you can configure Random generator with these settings:
510+
511+
```nginx
512+
set $session_random_length 16;
513+
```
514+
515+
Here follows the description of each setting:
516+
517+
**length**
518+
519+
`session.random.length` holds the length of the `session.id`. By default it is 16 bytes.
520+
This can be configured with Nginx `set $session_random_length 16;`.
521+
478522
## Lua API
479523

480524
### Functions and Methods
@@ -532,7 +576,7 @@ expiration time stored in a cookie.
532576
```lua
533577
local session = require "resty.session".open()
534578
-- Set some options (overwriting the defaults or nginx configuration variables)
535-
local session = require "resty.session".open{ identifier = { length = 32 }}
579+
local session = require "resty.session".open{ random = { length = 32 }}
536580
-- Read some data
537581
if session.present then
538582
ngx.print(session.data.uid)
@@ -564,7 +608,7 @@ new session was created (either because user client didn't send a cookie or that
564608
```lua
565609
local session = require "resty.session".start()
566610
-- Set some options (overwriting the defaults or nginx configuration variables)
567-
local session = require "resty.session".start{ identifier = { length = 32 }}
611+
local session = require "resty.session".start{ random = { length = 32 }}
568612
```
569613

570614
#### boolean, string session:regenerate(flush or nil)
@@ -639,12 +683,6 @@ object.
639683
`session.destroyed` can be used to check if the `session:destroy()` was called for the current session
640684
object. It will also set `session.opened`, `session.started`, and `session.present` to false.
641685

642-
643-
#### number session.identifier.length
644-
645-
`session.identifier.length` holds the length of the `session.id`. By default it is 16 bytes.
646-
This can be configured with Nginx `set $session_identifier_length 16;`.
647-
648686
#### string session.key
649687

650688
`session.key` holds the HMAC key. It is automatically generated. Nginx configuration like
@@ -741,8 +779,8 @@ parameter is used.
741779
#### boolean session.check.ssi
742780

743781
`session.check.ssi` is additional check to validate that the request was made with the same SSL
744-
session as when the original cookie was delivered. This check is enabled by default on non-persistent
745-
sessions and disabled by default on persistent sessions. Please note that on TLS with TLS Tickets enabled,
782+
session as when the original cookie was delivered. This check is enabled by default on releases prior 2.12 on non-persistent
783+
sessions and disabled by default on persistent sessions and on releases 2.12 and later. Please note that on TLS with TLS Tickets enabled,
746784
this will be empty) and not used. This is discussed on issue #5 (https://github.com/bungle/lua-resty-session/issues/5).
747785
You can disable TLS tickets with Nginx configuration:
748786

@@ -804,7 +842,9 @@ and `session.start`).
804842
Please note that Nginx has also its own SSL/TLS caches and timeouts. Especially note `ssl_session_timeout` if you
805843
are running services over SSL/TLS as this will end sessions regardless of `session.cookie.lifetime`. Please adjust
806844
that accordingly or disable `ssl_session_id` check `session.check.ssi = false` (in code) or
807-
`set $session_check_ssi off;` (in Nginx configuration).
845+
`set $session_check_ssi off;` (in Nginx configuration). As of 2.12 checking SSL session identifier check (`$session_check_ssi` / `session.check.ssi`)
846+
is disabled by default because it was not reliable (most servers use session tickets now), and it usually needed
847+
extra configuration.
808848

809849
You may want to add something like this to your Nginx SSL/TLS config (quite a huge cache in this example, 1 MB is
810850
about 4.000 SSL sessions):
@@ -846,12 +886,18 @@ set $session_cookie_samesite Lax;
846886
set $session_cookie_secure on;
847887
set $session_cookie_httponly on;
848888
set $session_cookie_delimiter |;
849-
set $session_check_ssi on;
889+
set $session_check_ssi off;
850890
set $session_check_ua on;
851891
set $session_check_scheme on;
852892
set $session_check_addr off;
893+
set $session_random_length 16;
894+
set $session_aes_mode cbc;
895+
set $session_aes_size 256;
896+
set $session_aes_hash sha512;
897+
set $session_aes_rounds 1;
898+
# this is removed in 2.12, use session_random_length instead:
853899
set $session_identifier_length 16;
854-
# these are deprecated in 2.1 and removed in 2.2, use session_aes_* instead
900+
# these are deprecated in 2.1 and removed in 2.2, use session_aes_* instead:
855901
set $session_cipher_mode cbc;
856902
set $session_cipher_size 256;
857903
set $session_cipher_hash sha512;

lib/resty/session.lua

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ local function enabled(val)
1919
end
2020

2121
local function setcookie(session, value, expires)
22+
if ngx.headers_sent then return nil, "Attempt to set session cookie after sending out response headers." end
2223
local c = session.cookie
2324
local i = 3
2425
local n = session.name .. "="
@@ -94,8 +95,8 @@ local function save(session, close)
9495
end
9596

9697
local function regenerate(session, flush)
97-
local i = session.present and session.id or nil
98-
session.id = random(session.identifier.length, true) or random(session.identifier.length)
98+
local i = session.present and session.id
99+
session.id = session:identifier()
99100
if flush then
100101
if i and session.storage.destroy then
101102
session.storage:destroy(i);
@@ -104,15 +105,15 @@ local function regenerate(session, flush)
104105
end
105106
end
106107

107-
local persistent = enabled(var.session_cookie_persistent or false)
108108
local defaults = {
109109
name = var.session_name or "session",
110+
identifier = var.session_identifier or "random",
110111
storage = var.session_storage or "cookie",
111112
serializer = var.session_serializer or "json",
112113
encoder = var.session_encoder or "base64",
113114
cipher = var.session_cipher or "aes",
114115
cookie = {
115-
persistent = persistent,
116+
persistent = enabled(var.session_cookie_persistent or false),
116117
renew = tonumber(var.session_cookie_renew) or 600,
117118
lifetime = tonumber(var.session_cookie_lifetime) or 3600,
118119
path = var.session_cookie_path or "/",
@@ -122,18 +123,17 @@ local defaults = {
122123
httponly = enabled(var.session_cookie_httponly or true),
123124
delimiter = var.session_cookie_delimiter or "|"
124125
}, check = {
125-
ssi = enabled(var.session_check_ssi or persistent == false),
126+
ssi = enabled(var.session_check_ssi or false),
126127
ua = enabled(var.session_check_ua or true),
127128
scheme = enabled(var.session_check_scheme or true),
128129
addr = enabled(var.session_check_addr or false)
129-
}, identifier = {
130-
length = tonumber(var.session_identifier_length) or 16
131-
}
130+
},
131+
132132
}
133133
defaults.secret = var.session_secret or random(32, true) or random(32)
134134

135135
local session = {
136-
_VERSION = "2.10"
136+
_VERSION = "2.12"
137137
}
138138

139139
session.__index = session
@@ -147,27 +147,31 @@ function session.new(opts)
147147
local a, b = y.cookie or z.cookie, z.cookie
148148
local c, d = y.check or z.check, z.check
149149
local e, f = y.cipher or z.cipher, z.cipher
150-
local g, h = y.identifier or z.identifier, z.identifier
151-
local o, i = pcall(require, "resty.session.storage." .. (y.storage or z.storage))
150+
local o, g = pcall(require, "resty.session.identifiers." .. (y.identifier or z.identifier))
151+
if not o then
152+
g = require "resty.session.identifiers.random"
153+
end
154+
local o, h = pcall(require, "resty.session.storage." .. (y.storage or z.storage))
152155
if not o then
153-
i = require "resty.session.storage.cookie"
156+
h = require "resty.session.storage.cookie"
154157
end
155-
local o, j = pcall(require, "resty.session.serializers." .. (y.serializer or z.serializer))
158+
local o, i = pcall(require, "resty.session.serializers." .. (y.serializer or z.serializer))
156159
if not o then
157-
j = require "resty.session.serializers.json"
160+
i = require "resty.session.serializers.json"
158161
end
159-
local o, k = pcall(require, "resty.session.encoders." .. (y.encoder or z.encoder))
162+
local o, j = pcall(require, "resty.session.encoders." .. (y.encoder or z.encoder))
160163
if not o then
161-
k = require "resty.session.encoders.base64"
164+
j = require "resty.session.encoders.base64"
162165
end
163-
local o, l = pcall(require, "resty.session.ciphers." .. (e or f))
166+
local o, k = pcall(require, "resty.session.ciphers." .. (e or f))
164167
if not o then
165-
l = require "resty.session.ciphers.aes"
168+
k = require "resty.session.ciphers.aes"
166169
end
167170
local self = {
168171
name = y.name or z.name,
169-
serializer = j,
170-
encoder = k,
172+
identifier = g,
173+
serializer = i,
174+
encoder = j,
171175
data = y.data or {},
172176
secret = y.secret or z.secret,
173177
cookie = {
@@ -185,12 +189,10 @@ function session.new(opts)
185189
ua = c.ua or d.ua,
186190
scheme = c.scheme or d.scheme,
187191
addr = c.addr or d.addr
188-
}, identifier = {
189-
length = g.length or h.length
190192
}
191193
}
192-
self.storage = i.new(self)
193-
self.cipher = l.new(self)
194+
self.storage = h.new(self)
195+
self.cipher = k.new(self)
194196
return setmetatable(self, session)
195197
end
196198

@@ -268,13 +270,16 @@ function session.start(opts)
268270
local self, present = session.open(opts)
269271
if present then
270272
if self.storage.start then
271-
self.storage:start(self.id)
273+
local ok, err = self.storage:start(self.id)
274+
if not ok then return nil, err end
272275
end
273276
if self.expires - time() < self.cookie.renew then
274-
save(self)
277+
local ok, err = save(self)
278+
if not ok then return nil, err end
275279
end
276280
else
277-
save(self)
281+
local ok, err = save(self)
282+
if not ok then return nil, err end
278283
end
279284
self.started = true
280285
return self, present
@@ -287,7 +292,7 @@ end
287292

288293
function session:save(close)
289294
if not self.id then
290-
self.id = random(self.identifier.length, true) or random(self.identifier.length)
295+
self.id = self:identifier()
291296
end
292297
return save(self, close ~= false)
293298
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
local tonumber = tonumber
2+
local random = require "resty.random".bytes
3+
local var = ngx.var
4+
5+
local defaults = {
6+
length = tonumber(var.session_random_length) or 16
7+
}
8+
9+
return function(config)
10+
local c = config.random or defaults
11+
local l = c.length or defaults.length
12+
return random(l, true) or random(l)
13+
end

lua-resty-session-dev-1.rockspec

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ source = {
44
url = "git://github.com/bungle/lua-resty-session.git"
55
}
66
description = {
7-
summary = "Session library for OpenResty implementing Secure Cookie Protocol",
7+
summary = "Session Library for OpenResty – Flexible and Secure",
88
detailed = "lua-resty-session is a secure, and flexible session library for OpenResty.",
99
homepage = "https://github.com/bungle/lua-resty-session",
1010
maintainer = "Aapo Talvensaari <[email protected]>",
@@ -16,17 +16,18 @@ dependencies = {
1616
build = {
1717
type = "builtin",
1818
modules = {
19-
["resty.session"] = "lib/resty/session.lua",
20-
["resty.session.storage.shm"] = "lib/resty/session/storage/shm.lua",
21-
["resty.session.storage.redis"] = "lib/resty/session/storage/redis.lua",
22-
["resty.session.storage.cookie"] = "lib/resty/session/storage/cookie.lua",
23-
["resty.session.storage.memcache"] = "lib/resty/session/storage/memcache.lua",
24-
["resty.session.storage.memcached"] = "lib/resty/session/storage/memcached.lua",
25-
["resty.session.ciphers.aes"] = "lib/resty/session/ciphers/aes.lua",
26-
["resty.session.ciphers.none"] = "lib/resty/session/ciphers/none.lua",
27-
["resty.session.encoders.hex"] = "lib/resty/session/encoders/hex.lua",
28-
["resty.session.encoders.base16"] = "lib/resty/session/encoders/base16.lua",
29-
["resty.session.encoders.base64"] = "lib/resty/session/encoders/base64.lua",
30-
["resty.session.serializers.json"] = "lib/resty/session/serializers/json.lua"
19+
["resty.session"] = "lib/resty/session.lua",
20+
["resty.session.identifiers.random"] = "lib/resty/session/identifiers/random.lua",
21+
["resty.session.storage.shm"] = "lib/resty/session/storage/shm.lua",
22+
["resty.session.storage.redis"] = "lib/resty/session/storage/redis.lua",
23+
["resty.session.storage.cookie"] = "lib/resty/session/storage/cookie.lua",
24+
["resty.session.storage.memcache"] = "lib/resty/session/storage/memcache.lua",
25+
["resty.session.storage.memcached"] = "lib/resty/session/storage/memcached.lua",
26+
["resty.session.ciphers.aes"] = "lib/resty/session/ciphers/aes.lua",
27+
["resty.session.ciphers.none"] = "lib/resty/session/ciphers/none.lua",
28+
["resty.session.encoders.hex"] = "lib/resty/session/encoders/hex.lua",
29+
["resty.session.encoders.base16"] = "lib/resty/session/encoders/base16.lua",
30+
["resty.session.encoders.base64"] = "lib/resty/session/encoders/base64.lua",
31+
["resty.session.serializers.json"] = "lib/resty/session/serializers/json.lua"
3132
}
3233
}

0 commit comments

Comments
 (0)