Skip to content

Instantly share code, notes, and snippets.

@tianchaijz
Created March 26, 2019 08:21
Show Gist options
  • Save tianchaijz/c58d8f65295334509f928ac2a3dab8e6 to your computer and use it in GitHub Desktop.
Save tianchaijz/c58d8f65295334509f928ac2a3dab8e6 to your computer and use it in GitHub Desktop.
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