前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >云实验室(18) - kong扩展redis-auth插件

云实验室(18) - kong扩展redis-auth插件

作者头像
惊羽-布壳儿
发布2022-06-15 21:16:33
4071
发布2022-06-15 21:16:33
举报
文章被收录于专栏:惊羽-布壳儿惊羽-布壳儿

1. 编写插件

代码参考 https://hub.fastgit.org/duyhotan2000/kong-plugin-auth-redis 感谢原作者的开源工作. 我们做了少量修改,结构效果如下:

代码源码 :

handle.lua

代码语言:javascript
复制
-- 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

header_filter.lua

代码语言:javascript
复制
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

schema.lua

代码语言:javascript
复制
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
}

2. 将插件挂载到kong

3.1 插件挂载

3.2 kong配置挂载(constants.lua)

3.3 修改(constants.lua)

3.4 重启kong

3.5 konga添加插件

3. 测试

3.1 请求 head 中没有放 "Authorization"

3.2 请求 head 中加上 "Authorization"

3.3 redis中添加key

3.4 再次请求

正常响应了

3.5 查看kong日志

用户信息已经放入了http head中,下游可直接食用,不在依赖进程会话.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 编写插件
    • handle.lua
      • header_filter.lua
        • schema.lua
        • 2. 将插件挂载到kong
          • 3.1 插件挂载
            • 3.2 kong配置挂载(constants.lua)
              • 3.3 修改(constants.lua)
                • 3.4 重启kong
                  • 3.5 konga添加插件
                  • 3. 测试
                    • 3.1 请求 head 中没有放 "Authorization"
                      • 3.2 请求 head 中加上 "Authorization"
                        • 3.3 redis中添加key
                          • 3.4 再次请求
                            • 3.5 查看kong日志
                            相关产品与服务
                            云数据库 Redis
                            腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档