Created
March 26, 2019 08:21
-
-
Save tianchaijz/c58d8f65295334509f928ac2a3dab8e6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local ngx = ngx | |
local md5 = ngx.md5 | |
local ngx_time = ngx.time | |
local ngx_cookie_time = ngx.cookie_time | |
local decode_base64 = ngx.decode_base64 | |
local string_sub = string.sub | |
local string_find = string.find | |
local string_format = string.format | |
local table_concat = table.concat | |
local default_cookie_name = "__basic_auth" | |
local default_cookie_age = 2592000 | |
local default_cookie_secret = "qG7o/lPFNgLrAwLG283fp18FjPWpZXv1WTE0rvY7o=" | |
local function encrypt(expiration, user, password, secret) | |
return md5(string_format( | |
"%d:%s:%s:%s", expiration, user, password, secret)) | |
end | |
local function check_cookie(user, password, name, secret) | |
local ck = ngx.var["cookie_" .. name] | |
if not ck then | |
return | |
end | |
local pos = string_find(ck, ":") | |
if not pos then | |
return | |
end | |
local expiration = tonumber(string_sub(ck, 1, pos - 1)) | |
if not expiration then | |
return | |
end | |
if ngx_time() > expiration then | |
return | |
end | |
return string_sub(ck, pos + 1) == | |
encrypt(expiration, user, password, secret) | |
end | |
local function set_cookie(user, password, name, secret, age) | |
local expiration = ngx_time() + age | |
local expires = ngx_cookie_time(expiration) | |
local ck = expiration .. ":" .. encrypt(expiration, user, password, secret) | |
local cookie = table_concat({ | |
name .. "=" .. ck, | |
"Expires=" .. expires, | |
"Max-Age=" .. age, | |
"Path=/", | |
"HttpOnly", | |
}, "; ") | |
ngx.header["Set-Cookie"] = cookie | |
end | |
local function basic_parse(header) | |
header = header or ngx.var.http_authorization | |
if not header then | |
return | |
end | |
local pos = string_find(header, "[Bb]asic ") | |
if pos ~= 1 then | |
return | |
end | |
local auth = decode_base64(string_sub(header, 7)) | |
if not auth then | |
return | |
end | |
pos = string_find(auth, ":") | |
if not pos then | |
return | |
end | |
return string_sub(auth, 1, pos - 1), string_sub(auth, pos + 1) | |
end | |
local function basic_test(user, password) | |
local u, p = basic_parse() | |
return u == user and p == password | |
end | |
local function unauthorized() | |
ngx.header.content_type = "text/plain" | |
ngx.header.www_authenticate = [[Basic realm="Restricted"]] | |
ngx.status = ngx.HTTP_UNAUTHORIZED | |
ngx.print("401 Unauthorized") | |
return ngx.exit(ngx.HTTP_OK) | |
end | |
local _M = {} | |
_M.basic_test = basic_test | |
_M.unauthorized = unauthorized | |
function _M.basic_check(user, password) | |
if not basic_test(user, password) then | |
return unauthorized() | |
end | |
end | |
--[[ | |
auth = { | |
user = user, | |
password = password, | |
cookie = { | |
name = name, secret = secret, age = age | |
} | |
} | |
--]] | |
function _M.check(auth) | |
local user, password = auth.user, auth.password | |
local cookie = auth.cookie or {} | |
local name = cookie.name or default_cookie_name | |
local secret = cookie.secret or default_cookie_secret | |
local age = cookie.age or default_cookie_age | |
if check_cookie(user, password, name, secret) then | |
return | |
end | |
if basic_test(user, password) then | |
set_cookie(user, password, name, secret, age) | |
return | |
end | |
return unauthorized() | |
end | |
_M.basic_parse = basic_parse | |
_M.check({ | |
user = "your-user", | |
password = "your-password", | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment