代码参考 https://hub.fastgit.org/duyhotan2000/kong-plugin-auth-redis 感谢原作者的开源工作. 我们做了少量修改,结构效果如下:
代码源码 :
-- Extending the Base Plugin handler is optional, as there is no real
-- concept of interface in Lua, but the Base Plugin handler's methods
-- can be called from your child implementation and will print logs
-- in your `error.log` file (where all logs are printed).
local BasePlugin = require "kong.plugins.base_plugin"
local RedisToken = BasePlugin:extend()
local header_filter = require "kong.plugins.auth-redis.header_filter"
-- Your plugin handler's constructor. If you are extending the
-- Base Plugin handler, it's only role is to instanciate itself
-- with a name. The name is your plugin name as it will be printed in the logs.
function RedisToken:new()
RedisToken.super.new(self, "auth-redis")
end
function RedisToken:access(config)
-- Eventually, execute the parent implementation
-- (will log that your plugin is entering this context)
RedisToken.super.access(self)
header_filter.execute(config, ngx)
end
return RedisToken
local redis = require "resty.redis"
local _M = {}
function _M.execute(conf, ngx)
-- Get request Header and check if exist
local ngx_headers = kong.request.get_headers()
local auth, err = ngx_headers["Authorization"]
if not auth and conf.allow_anonymous == 0 then -- 1 = Allow anonymous forward request, 0 = Disallow, return 401 as default
return kong.response.exit(401, { message = "Unauthorized" })
end
if not auth and conf.allow_anonymous == 1 then
kong.service.request.clear_header("Authorization")
return
end
-- Init Redis connection
local red = redis:new()
red:set_timeout(conf.redis_timeout)
-- Connect to redis
local ok, err = red:connect(conf.redis_host, conf.redis_port)
if not ok then
return kong.response.exit(503, "Session Service Temporarily Unavailable")
end
-- end
-- Auth Redis connection with password
if conf.redis_password and conf.redis_password ~= "" then
local ok, err = red:auth(conf.redis_password)
if not ok then
return kong.response.exit(503, "Session Service Temporarily Unavailable")
end
end
-- Query token in Redis
local token = auth
--if string.len(conf.redis_token_prefix) > 0 then
-- token = conf.redis_token_prefix .. ":" .. string.sub(auth, 8)
--else
-- token = string.sub(auth, 8)
--end
local verify, err = red:get(token)
kong.log("verify", verify);
if err then
return kong.response.exit(503, "Session Service Temporarily Unavailable")
end
if not verify then
return kong.response.exit(503, "Session Service Temporarily Unavailable")
end
-- Keep Established Redis connection
local ok, err = red:set_keepalive(60000,5000)
if not ok then
kong.log.err("failed to set Session keepalive: ", err)
end
if verify == ngx.null then
return kong.response.exit(401, { message = "Unauthorized" })
elseif conf.allow_anonymous == 1 then
kong.service.request.clear_header("Authorization")
return
else
kong.service.request.set_header("Authorization", "Bearer " .. verify)
end
-- Close Redis connection
-- local ok, err = red:close()
end
return _M
local redis = require "resty.redis"
return {
fields = {
redis_token_prefix = {
type = "string",
default = ""
},
redis_host = {
type = "string"
},
redis_port = {
type = "number",
default = 6379
},
redis_password = {
type = "string"
},
redis_timeout = {
type = "number",
default = 2000
},
allow_anonymous = {
type = "number",
default = 0
}
},
self_check = function(schema, plugin_t, dao, is_updating)
if not plugin_t.redis_host then
return false, kong.response.exit(500, "You need to specify a Redis host")
elseif not plugin_t.redis_port then
return false, kong.response.exit(500, "You need to specify a Redis port")
elseif not plugin_t.redis_timeout then
return false, kong.response.exit(500, "You need to specify a Redis timeout")
end
local red = redis:new()
red:set_timeout(plugin_t.redis_timeout)
local ok, err = red:connect(plugin_t.redis_host, plugin_t.redis_port)
if not ok then
return false, kong.response.exit(500, "Redis Host unreachable: " .. err)
end
if plugin_t.redis_password and plugin_t.redis_password ~= "" then
local ok, err = red:auth(plugin_t.redis_password)
if not ok then
return false, kong.response.exit(500, "Redis Invalid Credentials: " .. err)
end
end
return true
end
}
正常响应了
用户信息已经放入了http head中,下游可直接食用,不在依赖进程会话.