API网关-Kong-AES加密插件编写

2018年10月29日
kong version: 0.14.1

需求:

最近开始使用了一个API网关软件 Kong,可实现登录认证、监控、权限控制等内容。

在使用的过程中约到了一个问题,同一个前端应用请求了api分别由两个服务提供,两个服务有公用的user_id,
但是又有不同的认证方式,感觉好麻烦,但是又必须搞
如图:

请求过程

分析:

1)客户端携带由B的consumer信息加工而成的jwt,请求B

2)B 解密JWT产生consumer-id、customer-id(对应应用中的user id),放入请求头中

3)请求C应用时需要将customer-id进行aes加密,并放入header中,(需要Kong 插件处理

4)请求D应用时只需customer-id即可,(无需关注

实现:

  1. 首先了解一下Kong的插件结构,以及使用方式
    Kong 自定义插件
<plugin-name>
├── INSTALL.txt
├── README.md
├── kong
│   └── plugins
│       └── <plugin-name>
│           ├── handler.lua
│           └── schema.lua
└── <plugin-name>-<version>.rockspec

使用docker-compose启动Kong

  kong:
    image: kong
    environment:
     // 配置插件地址及名称
      KONG_LUA_PACKAGE_PATH: /kong-plugins/?.lua;;
      KONG_CUSTOM_PLUGINS: aes256_encrypt
    volumes:
      // 挂载插件文件
      - ./kong/:/kong-plugins/kong/
  1. schema.lua
    配置启动插件时所需要的参数,并进行校验
return {
    no_consumer = true,
    fields = {
        -- 加密的密码配置
        secret = {type = "string", default = "", fun = check_secret},
        -- 匿名配置
        anonymous = {type = "string", default = "", func = check_user},
    },
    self_check = function(schema, plugin_t, dao, is_updating)
        -- perform any custom verification
        return true
    end
}
  1. handler.lua
    具体的处理过程
local singletons = require "kong.singletons"
local responses = require "kong.tools.responses"
local BasePlugin = require "kong.plugins.base_plugin"
local aes_cipher = require "kong.plugins.aes256_encrypt.aes_cipher"

-- header的读取
local ngx_set_header = ngx.req.set_header
-- header的设置
local ngx_get_header = ngx.req.get_headers

local Aes256Encrypt = BasePlugin:extend()

Aes256Encrypt.VERSION = "0.1.0"
-- PRIORITY 越大执行顺序月靠前
-- jwt 1005,放到jwt后面执行
Aes256Encrypt.PRIORITY = 1000

-- 请求时的处理过程
function Aes256Encrypt:access(config)
    Aes256Encrypt.super.access(self)

    -- 使用了 aes-256-cbc加密
    local aes_type = 'aes-256-cbc'

    local password = config.secret
    local anonymous = config.anonymous
    local authorization = ngx_get_header()['authorization']
    local consumer_customer_id = ngx_get_header()['x-consumer-custom-id']
    -- 请求时没有认证信息,但是有匿名设置
    -- 将得到 consumer_customer_id,供下一步使用
    if authorization == nil then
        if anonymous ~= nil then
            local result, err = singletons.db.consumers:select { id = anonymous }
            if result ~= nil then
                consumer_customer_id = result.custom_id
                ngx_set_header('x-consumer-custom-id', result.custom_id)
                ngx_set_header('x-consumer-username', result.username)
                ngx_set_header('x-consumer-id', result.id)
                ngx_set_header('x-anonymous-consumer', true)
            else
                return responses.send(403, "missing authorization error anonymous")
            end
        else
            return responses.send(403, "missing authorization none anonymous")
        end
    end

    -- 得到 consumer_customer_id
    -- 继续加密处理
    if consumer_customer_id ~= nil then
        local encrypted_str = aes_cipher.encrypt(aes_type, password, consumer_customer_id)
        ngx_set_header('authorization', 'Bearer'..' '..encrypted_str)
    end

    -- Implement any custom logic here
end
-- container name aes256_kong_1
-- padding   PKCS5Padding
  1. cipher.lua
    调用了一个openssl库-luaossl,自己实现有点难,
    这个库找了好久,可能用lua的人太少了吧,我就是头一次用🤣🤣🤣
    突然发现nodejs一大堆的库还是挺好用的
local rand = require('openssl.rand')
local cipher = require('openssl.cipher')

function binary_2_hex(str)
    return (str:gsub('.', function (c)
        return string.format('%02X', string.byte(c))
    end))
end


function hex_2_binary(str)
    return (str:gsub('..', function (cc)
        return string.char(tonumber(cc, 16))
    end))
end

function encrypt(type, pass, text)
    local iv = rand.bytes(16)

    return binary_2_hex(iv..cipher.new(type):encrypt(pass, iv):final(text))
end

function decrypt(type, pass, encrypted)
    local iv = hex_2_binary(encrypted:sub(0 + 1, 31 + 1))
    local string = hex_2_binary(encrypted:sub(32 + 1))

    return cipher.new(type):decrypt(pass, iv):final(string)
end

export_module = {}

export_module.encrypt = encrypt
export_module.decrypt = decrypt

return export_module

启动测试

使用docker镜像启动,安装方便

启动kong以及对应的UI
docker-compose up -d
启动一个简单的node服务查看加密结果
node server.js

localcalhost:1337 进行配置和测试

需要配置路由、添加使用jwt、aes256_encrypt插件

奉上github代码

初来乍到,有错误的地方欢迎指点,感谢~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • Kong 是 Mashape 开源的高性能高可用 API 网关和 API 管理服务层。它基于 OpenResty ...
    meng_philip123阅读 9,038评论 0 6
  • kong简介 Kong 是在客户端和(微)服务间转发API通信的API网关,通过插件扩展功能。Kong 有两个主要...
    pingforever阅读 11,564评论 0 10
  • 更新,现在有更强大的API网关,国产 Apache APISIX,可自行谷歌。 本文转载自选择Kong作为你的AP...
    tenlee阅读 3,674评论 0 9
  • 1. Kong简介 Kong是一款基于OpenResty(Nginx + Lua模块)编写的高可用、易扩展的,由M...
    garyond阅读 5,825评论 0 18