lolly/docs/lua/authentication/basic_auth.lua
xfy 6543422281 docs: 添加 Nginx 配置和 Lua 脚本示例文档
- config: 反向代理、缓存、负载均衡、安全、SSL 等配置模板
- lua: API 网关、认证、动态路由、限流、WebSocket 等脚本示例

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 17:59:22 +08:00

88 lines
2.4 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Basic Auth 验证示例
--
-- 功能:解析 Authorization 头中的 Basic 凭据,
-- 校验用户名密码,失败返回 401。
--
-- 依赖OpenResty (ngx.*, cjson)
--
-- 使用方式(在 nginx.conf 中):
-- access_by_lua_file /path/to/basic_auth.lua;
-- ==================== 配置 ====================
-- 用户凭据表(生产环境应使用 Redis / 数据库)
local USERS = {
["admin"] = "admin-secret",
["reader"] = "read-only-pass",
}
-- 认证域名称(浏览器弹窗显示的名称)
local REALM = "Lolly API Gateway"
-- 是否跳过 OPTIONS 预检请求
local SKIP_PREFLIGHT = true
-- ==================== 工具函数 ====================
local cjson = require("cjson.safe")
--- 校验用户名密码
local function authenticate(username, password)
local expected = USERS[username]
if not expected then
return false
end
return expected == password
end
--- 返回 401 响应,附带 WWW-Authenticate 头
local function challenge(err_msg)
ngx.status = 401
ngx.header["WWW-Authenticate"] = 'Basic realm="' .. REALM .. '", charset="UTF-8"'
ngx.header["Content-Type"] = "application/json"
ngx.say(cjson.encode({
error = "unauthorized",
message = err_msg or "Valid credentials required",
}))
return ngx.exit(401)
end
-- ==================== 主逻辑 ====================
-- 跳过 OPTIONS 预检请求
if SKIP_PREFLIGHT and ngx.req.get_method() == "OPTIONS" then
return
end
-- 提取 Authorization Header
local auth_header = ngx.req.get_headers()["Authorization"]
if not auth_header then
return challenge("Missing Authorization header")
end
-- 验证是否为 Basic 类型
local credentials = auth_header:match("^%s*Basic%s+(.+)$")
if not credentials then
return challenge("Invalid Authorization scheme, expected Basic")
end
-- 解码 Base64
local decoded = ngx.decode_base64(credentials)
if not decoded then
return challenge("Invalid Base64 encoding in credentials")
end
-- 分割 username:password
local username, password = decoded:match("^([^:]+):(.+)$")
if not username or not password then
return challenge("Credentials must be in username:password format")
end
-- 校验凭据
if not authenticate(username, password) then
return challenge("Invalid username or password")
end
-- 验证通过,将用户名存入 ngx.ctx 供后续阶段使用
ngx.ctx.auth_user = username