1
- local ngx_var = ngx .var
2
- local ngx_header = ngx .header
1
+ local require = require
2
+ local var = ngx .var
3
+ local header = ngx .header
3
4
local concat = table.concat
4
5
local hmac = ngx .hmac_sha1
5
6
local time = ngx .time
6
7
local http_time = ngx .http_time
8
+ local find = string.find
7
9
local type = type
10
+ local pcall = pcall
11
+ local tonumber = tonumber
8
12
local setmetatable = setmetatable
13
+ local getmetatable = getmetatable
9
14
local ffi = require " ffi"
10
15
local ffi_cdef = ffi .cdef
11
16
local ffi_new = ffi .new
33
38
34
39
local function setcookie (session , value , expires )
35
40
local c = session .cookie
36
- local cookie = { session .name , " =" , value or " " }
37
- local domain = c .domain
41
+ local i = 3
42
+ local n = session .name .. " ="
43
+ local k = { n , value or " " }
44
+ local d = c .domain
38
45
if expires then
39
- cookie [# cookie + 1 ] = " ; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Max-Age=0"
46
+ k [i ] = " ; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Max-Age=0"
47
+ i = i + 1
40
48
elseif c .persistent then
41
- cookie [# cookie + 1 ] = " ; Expires="
42
- cookie [# cookie + 1 ] = http_time (session .expires )
43
- cookie [# cookie + 1 ] = " ; Max-Age="
44
- cookie [# cookie + 1 ] = c .lifetime
49
+ k [i ] = " ; Expires="
50
+ k [i + 1 ] = http_time (session .expires )
51
+ k [i + 2 ] = " ; Max-Age="
52
+ k [i + 3 ] = c .lifetime
53
+ i = i + 4
45
54
end
46
- if domain and domain ~= " localhost" and domain ~= " " then
47
- cookie [# cookie + 1 ] = " ; Domain="
48
- cookie [# cookie + 1 ] = domain
55
+ if d and d ~= " localhost" and d ~= " " then
56
+ k [i ] = " ; Domain="
57
+ k [i + 1 ] = d
58
+ i = i + 2
59
+ end
60
+ k [i ] = " ; Path="
61
+ k [i + 1 ] = c .path or " /"
62
+ i = i + 2
63
+ if c .samesite == " Lax" or c .samesite == " Strict" then
64
+ k [i ] = " ; SameSite="
65
+ k [i + 1 ] = c .samesite
66
+ i = i + 2
49
67
end
50
- cookie [# cookie + 1 ] = " ; Path="
51
- cookie [# cookie + 1 ] = c .path or " /"
52
68
if c .secure then
53
- cookie [# cookie + 1 ] = " ; Secure"
69
+ k [i ] = " ; Secure"
70
+ i = i + 1
54
71
end
55
72
if c .httponly then
56
- cookie [# cookie + 1 ] = " ; HttpOnly"
73
+ k [i ] = " ; HttpOnly"
74
+ i = i + 1
57
75
end
58
- local needle = concat (cookie , nil , 1 , 2 )
59
- cookie = concat (cookie )
60
- local cookies = ngx_header [" Set-Cookie" ]
61
- local t = type (cookies )
76
+ k = concat (k )
77
+ local s = header [" Set-Cookie" ]
78
+ local t = type (s )
62
79
if t == " table" then
63
- local found = false
64
- for i , c in ipairs (cookies ) do
65
- if c :find (needle , 1 , true ) == 1 then
66
- cookies [i ] = cookie
67
- found = true
80
+ local f = false
81
+ local z = # s
82
+ for i = 1 , z do
83
+ if find (s [i ], n , 1 , true ) == 1 then
84
+ s [i ] = k
85
+ f = true
68
86
break
69
87
end
70
88
end
71
- if not found then
72
- cookies [ # cookies + 1 ] = cookie
89
+ if not f then
90
+ s [ z + 1 ] = k
73
91
end
74
- elseif t == " string" and cookies : find (needle , 1 , true ) ~= 1 then
75
- cookies = { cookies , cookie }
92
+ elseif t == " string" and find (s , n , 1 , true ) ~= 1 then
93
+ s = { s , k }
76
94
else
77
- cookies = cookie
95
+ s = k
78
96
end
79
- ngx_header [" Set-Cookie" ] = cookies
97
+ header [" Set-Cookie" ] = s
80
98
return true
81
99
end
82
100
@@ -104,35 +122,36 @@ local function regenerate(session, flush)
104
122
end
105
123
end
106
124
107
- local persistent = enabled (ngx_var .session_cookie_persistent or false )
125
+ local persistent = enabled (var .session_cookie_persistent or false )
108
126
local defaults = {
109
- name = ngx_var .session_name or " session" ,
110
- storage = ngx_var .session_storage or " cookie" ,
111
- serializer = ngx_var .session_serializer or " json" ,
112
- encoder = ngx_var .session_encoder or " base64" ,
113
- cipher = ngx_var .session_cipher or " aes" ,
127
+ name = var .session_name or " session" ,
128
+ storage = var .session_storage or " cookie" ,
129
+ serializer = var .session_serializer or " json" ,
130
+ encoder = var .session_encoder or " base64" ,
131
+ cipher = var .session_cipher or " aes" ,
114
132
cookie = {
115
133
persistent = persistent ,
116
- renew = tonumber (ngx_var .session_cookie_renew ) or 600 ,
117
- lifetime = tonumber (ngx_var .session_cookie_lifetime ) or 3600 ,
118
- path = ngx_var .session_cookie_path or " /" ,
119
- domain = ngx_var .session_cookie_domain ,
120
- secure = enabled (ngx_var .session_cookie_secure ),
121
- httponly = enabled (ngx_var .session_cookie_httponly or true ),
122
- delimiter = ngx_var .session_cookie_delimiter or " |"
134
+ renew = tonumber (var .session_cookie_renew ) or 600 ,
135
+ lifetime = tonumber (var .session_cookie_lifetime ) or 3600 ,
136
+ path = var .session_cookie_path or " /" ,
137
+ domain = var .session_cookie_domain ,
138
+ secure = enabled (var .session_cookie_secure ),
139
+ httponly = enabled (var .session_cookie_httponly or true ),
140
+ samesite = var .session_cookie_samesite or " Lax" ,
141
+ delimiter = var .session_cookie_delimiter or " |"
123
142
}, check = {
124
- ssi = enabled (ngx_var .session_check_ssi or persistent == false ),
125
- ua = enabled (ngx_var .session_check_ua or true ),
126
- scheme = enabled (ngx_var .session_check_scheme or true ),
127
- addr = enabled (ngx_var .session_check_addr or false )
143
+ ssi = enabled (var .session_check_ssi or persistent == false ),
144
+ ua = enabled (var .session_check_ua or true ),
145
+ scheme = enabled (var .session_check_scheme or true ),
146
+ addr = enabled (var .session_check_addr or false )
128
147
}, identifier = {
129
- length = tonumber (ngx_var .session_identifier_length ) or 16
148
+ length = tonumber (var .session_identifier_length ) or 16
130
149
}
131
150
}
132
- defaults .secret = ngx_var .session_secret or random (32 )
151
+ defaults .secret = var .session_secret or random (32 )
133
152
134
153
local session = {
135
- _VERSION = " 2.2 "
154
+ _VERSION = " 2.3-dev "
136
155
}
137
156
138
157
session .__index = session
@@ -177,6 +196,7 @@ function session.new(opts)
177
196
domain = a .domain or b .domain ,
178
197
secure = a .secure or b .secure ,
179
198
httponly = a .httponly or b .httponly ,
199
+ samesite = a .samesite or b .samesite ,
180
200
delimiter = a .delimiter or b .delimiter
181
201
}, check = {
182
202
ssi = c .ssi or d .ssi ,
@@ -201,43 +221,43 @@ function session.open(opts)
201
221
else
202
222
self = session .new (opts )
203
223
end
204
- local scheme = ngx_header [" X-Forwarded-Proto" ]
224
+ local scheme = header [" X-Forwarded-Proto" ]
205
225
if self .cookie .secure == nil then
206
226
if scheme then
207
227
self .cookie .secure = scheme == " https"
208
228
else
209
- self .cookie .secure = ngx_var .https == " on"
229
+ self .cookie .secure = var .https == " on"
210
230
end
211
231
end
212
- scheme = self .check .scheme and (scheme or ngx_var .scheme or " " ) or " "
232
+ scheme = self .check .scheme and (scheme or var .scheme or " " ) or " "
213
233
local addr = " "
214
234
if self .check .addr then
215
- addr = ngx_header [" CF-Connecting-IP" ] or
216
- ngx_header [" Fastly-Client-IP" ] or
217
- ngx_header [" Incap-Client-IP" ] or
218
- ngx_header [" X-Real-IP" ]
235
+ addr = header [" CF-Connecting-IP" ] or
236
+ header [" Fastly-Client-IP" ] or
237
+ header [" Incap-Client-IP" ] or
238
+ header [" X-Real-IP" ]
219
239
if not addr then
220
- addr = ngx_header [" X-Forwarded-For" ]
240
+ addr = header [" X-Forwarded-For" ]
221
241
if addr then
222
242
-- We shouldn't really get the left-most address, because of spoofing,
223
243
-- but this is better handled with a module, like nginx realip module,
224
244
-- anyway (see also: http://goo.gl/Z6u2oR).
225
- local s = ( addr : find (' ,' , 1 , true ) )
245
+ local s = find (addr , ' ,' , 1 , true )
226
246
if s then
227
247
addr = addr :sub (1 , s - 1 )
228
248
end
229
249
else
230
- addr = ngx_var .remote_addr
250
+ addr = var .remote_addr
231
251
end
232
252
end
233
253
end
234
254
self .key = concat {
235
- self .check .ssi and (ngx_var .ssl_session_id or " " ) or " " ,
236
- self .check .ua and (ngx_var .http_user_agent or " " ) or " " ,
255
+ self .check .ssi and (var .ssl_session_id or " " ) or " " ,
256
+ self .check .ua and (var .http_user_agent or " " ) or " " ,
237
257
addr ,
238
258
scheme
239
259
}
240
- local cookie = ngx_var [" cookie_" .. self .name ]
260
+ local cookie = var [" cookie_" .. self .name ]
241
261
if cookie then
242
262
local i , e , d , h = self .storage :open (cookie , self .cookie .lifetime )
243
263
if i and e and e > time () and d and h then
@@ -283,8 +303,11 @@ function session:regenerate(flush)
283
303
return save (self )
284
304
end
285
305
286
- function session :save ()
287
- return save (self , true )
306
+ function session :save (close )
307
+ if not self .id then
308
+ self .id = random (self .identifier .length )
309
+ end
310
+ return save (self , close )
288
311
end
289
312
290
313
function session :destroy ()
0 commit comments