使用Kong来管理业务侧restful api

使用Kong来管理业务侧restful api

导言

Kong是一个集成了Nginx的工具,除了具有正向/反向代理的功能以外,其还能扩展业务侧API,为业务侧API加入认证,流控和管理等功能。Kong能够充当任何HTTP资源的门户,做为代理服务器或网关,同时经过插件提供了日志记录,身份认证,流量控制等功能。html

建议已提早了解过如下技术点和知识

1,正向代理和反向代理的概念
2,Linux系列的系统的命令及其简单操做
3,Nginx的简单运用
4,Lua语言简单语法 
5,CA--证书认证机构
6,restful API的特色
7,Http 基本认证
8,PostgreSQL的简单使用
9,OpenSSL,https协议与http协议的联系,区别nginx

1、以Ubuntu Linux 为例子,安装Kong

(1)打开Kong的官网:docker

https://getkong.org/数据库

点击“Quick Start”,开始进入安装简介页面。

能够看出,目前Kong可以安装在Linux阵营的系统或者docker等容器内。因此本文档就以UBUNTU为例,讲述Kong的安装特别是Kong的使用和管理Api等内容。ubuntu

(2)在安装简介页面点击你想安装在哪种系统或容器中,本文档已ubuntu为例,进行安装:点击Ubuntu图标,进入一个安装包下载页面,选择好本身Ubuntu系统的版本号对应的安装包下载便可。 api

(3)对下载好的安装包,进行安装,能够参考官方提供的如下3句命令:服务器

$ sudo apt-get update  
$ sudo apt-get install netcat openssl libpcre3 dnsmasq procps perl  
$ sudo dpkg -i kong-0.9.3.*.deb

(4)因为Kong做为一个工具,有部分本身的信息须要数据库进行存储,这样才能正常进行,而目前Kong支持的数据库官方给出的内容是:“Kong supports both PostgreSQL 9.4+ and Cassandra 2.2.x ”,即至少要安装PostgreSQL或者Cassandra两种数据库的其中一种。本文档以PostgreSQL为例子,与Kong进行配置集成。PostgreSQL具体能够参考:restful

http://www.cnblogs.com/sparkdev/p/5678874.html架构

(5)安装好PostgreSQL后,须要为Kong建立一个数据库而且须要一个名字为kong的数据库管理员。使用PostgreSQL建立用户和数据库,能够参考下面的代码:app

CREATE USER kong; CREATE DATABASE kong OWNER kong;

(6)创建好帐号后,须要对Kong进行数据库配置。找到Kong的配置文件kong.conf ,进行链接项修改:
 
(7)前面的步骤若是完成了,不出意外,就能够启动Kong了。命令:

sudo kong start --conf /etc/kong/kong.conf

2、将本身的Restful Api加入到Kong中,进行管理

(1)首先,要将本身的restful api服务部署好并启动。例如,咱们在172.31.31.128机器上面部署了一套restful API,以下图所示。这套api将做为咱们要加入到kong中的一个demo

(2)查阅Kong的5分钟快速启动指南,或者Kong自身的API文档,准备好使用kong的自身API对本身业务侧的restful API的管控。参考文档的地址以下: 
《Kong-快速加入你的API》: https://getkong.org/docs/0.9.x/getting-started/adding-your-api/
《Kong-Add API》: https://getkong.org/docs/0.9.x/admin-api/#add-api

由文档中,能够看出,该kong自身的Api中,Post方法的/apis/地址接口,对应的是增长一个(一组)业务侧的api。在列出的6个参数中,其中有几个重要的参数:name,requestpath, upstreamurl
(3)若是Kong成功启动了,那么使用Kong自身的API的话,默认是8001端口。例如上面所说的Kong自身的Post /apis/ 接口,Kong部署到192.168.26.128,则使用它的时候,url为: http://192.168.26.128:8001/apis/ 或者 http://localhost:8001/apis/。
(4)将以前已经部署好的业务侧的API加入到Kong中:
命令:

curl -i -X POST --url http://localhost:8001/apis/ --data 'name=message_api' --data 'upstream_url=https://172.31.31.128:8183/' --data 'request_path=/'

这里的upstreamurl 即上游地址,指向以前部署好的业务侧接口API,其中"requestpath=/"表明的是该部署好的服务器下的全部API都被放入kong中受控。name=message_api该参数时给Kong自身的API使用的,至关于一个id。例如调用删除接口或者认证接口的时候须要在url中指定该值做为参数,让Kong一一对应找到它所包含的业务侧API进行相关操做。这样,就至关于kong已经代理好了咱们以前在172.31.31.128部署好的业务侧的API。 
(5)经过Kong的反向代理,对业务侧的API进行访问。这个时候,咱们只须要在url中填写Kong服务器所在的地址便可:

 
由上图能够看出,咱们此次url上面的地址是kong的服务器IP地址192.168.26.128 。但实际上访问它的时候,已经能够去到部署到172.31.31.128的业务侧API。这是由于Kong作了反向代理。API的调用方客户能够彻底不知道经历了这一个过程。

3、将接入到Kong中的业务侧API加上认证管理

(1)使用Kong自带的“key-auth”插件对刚才加入的业务侧API进行认证受控。 命令:

curl -i -X POST --url http://localhost:8001/apis/message_api/plugins --data 'name=key-auth'


这个时候若是再次访问上面例子中的GET /users接口的话,就会被禁止,而且提示401说未认证访问的提示。

(2)同步业务侧的认证数据到kong,让kong去进行api的认证工做。例如业务侧的数据库有appKey和appSecret两个fields做为合法性认证的值。则能够参考使用下面的语句进行同步到kong的配置信息数据库PostgreSQL中:
命令:

curl -i -X POST --url http://localhost:8001/consumers/ --data "username=APPKEY_01"
curl -i -X POST --url http://localhost:8001/consumers/APPKEY_01/key-auth/ --data 'key=BASE64_APPKEY_01_APPSECRET_01'

我这里只是用了APPKEY01,APPSECRET01这样指代的值,实际操做中,应该填入真实的数据库值信息。而且BASE64_APPKEY01APPSECRET01是指代使用Base64或者其加密的方法获得的一种密文。
(3)对于受控的业务侧API的访问,须要在请求的Header中加入apiKey的参数和以前已经同步给Kong的密文。例以下面这样,填入后,就能够访问了:

4、Kong目前版本及其插件,还不能知足咱们Api的一些需求

(1)上面第三节中,咱们已经把部署在172.31.31.128服务器的业务侧restful API加入到Kong进行接口的身份认证,这也是咱们想要的效果。但同时,这样也意味着,对于这一套业务侧的API的每个接口,调用方的客户在调用的时候都须要在请求的Header中加入apiKey的参数和以前已经同步给Kong。身份认证经过了,才可以真正访问获得API并返回数据。例如咱们的业务侧的API有如下这样的一些典型的restful风格的API:

像这列表中的一系列的接口,都会被加入到Kong中,经过身份认证后才能访问。
(2)有时候,一些系统中,总会有一些不须要认证就能够直接使用的接口,例如一些系统的注册接口等,由于用户尚未注册,即尚未本身的帐号,因此是不须要进行身份认证的。restful 风格的API有一个显著的特色就是,请求的方法不一样,表明的接口也是不一样的。例如 POST /applications 接口与GET /applications 接口,虽然表面看url是同样的,但实际上倒是两个接口。
目前Kong的版本好似只有对一个URL地址下的API进行认证,即只达到路径这一粒度的,尚未作到路径上面还区分不一样的方法例如POST、DELETE、GET等区别对待的认证,即“路径+方法”这一粒度的。
例如:

这样的典型restful api中,目前全部的接口都已经在kong中作了认证受控。但若是对于applications资源,我只但愿POST方法这一条api进行特别处理,即不须要认证受控,则目前Kong以及它自带的插好似作不了。

5、使用Lua开发本身的Kong插件,过滤请求的Http协议动词

Kong做为一个开源产品,有一个很是吸引人的地方就是能够自由使用插件,而且还能够是使用本身写的插件,知足特定的业务需求。只要使用Lua语音,编写好逻辑,创建好符合Kong规范的lua文件架构,Kong就能够自动装载和识别这些控件,给须要的Api使用。
(1)Kong插件的文件架构
最简单的Kong插件开发,只须要完成handler.lua 和 schema.lua 这两个文件的编码便可。
其中handler.lua文件用于存放插件的须要完成的特定逻辑,而schema.lua至关于配置文件,用于存储一些handler.lua中可能须要用到的可配置变量的值。
(2)Kong的插件通常存放在如下系统目录下(以Ubuntu系统为例):/usr/local/share/lua/5.1/kong/plugins/ ,咱们使用目录列表语句,能够查阅到该文件夹下到底有哪些Kong的插件:
 
Kong有自动检查插件的机制,只要咱们在这个路径下,新建一个有必定含义来命名的文件夹,并将handler.lua 和 schema.lua放入该文件夹内,则Kong就会自动扫描到并添加这一个插件,并且插件的名称就是该文件夹的名称。例如该路径下有一个命名为“key-auth”的文件夹,其就是以前咱们所用到的“key-auth”插件。
(3)仿造“key-auth”插件,改写为知足本身需求的新插件。 Kong做为一个开源产品,它的内部的插件也是开放源代码的。咱们能够直接查阅它们的逻辑代码甚至改写。首先,咱们能够在Kong的插件路径下,新建一个“new-key-auth”的文件夹,而后将key-auth插件的全部的源码文件都copy到该文件夹下。

参考命令:

sudo mkdir new-key-auth 
sudo cp -a ./key-auth/* ./new-key-auth

因为key-auth插件只作到了路径这一级粒度的认证,没有作到路径+Http方法这一级粒度的认证,全部,咱们就参考模仿它,而后把Http方法加上去!
首先在schema.lua中新增一些关于不须要认证的Http方法的配置: 参考代码:

local function default_key_names(t)
  if not t.key_names then
    return {"apikey"}
  end
end

-- new default value function
local function default_not_need_auth_http_methods(t)
  if not t.not_need_auth_http_methods then
    return {"POST"}
  end
end

return {
  no_consumer = true,
  fields = {
    key_names = {required = true, type = "array", default = default_key_names},
    hide_credentials = {type = "boolean", default = false},
    -- new field
    not_need_auth_http_methods = {required = true, type = "array", default = default_not_need_auth_http_methods}
  }
}

这里咱们新增了一个default_not_need_auth_http_methods(t)方法,以及一个not_need_auth_http_methods的配置。咱们这里默认"POST"的Http方法不须要认证
接着,咱们在handler.lua中,找到function KeyAuthHandler:access(conf)这一方法,将这些配置加入到逻辑判断中:
参考代码:

function KeyAuthHandler:access(conf)
  KeyAuthHandler.super.access(self)

  local request_method = string.upper(ngx.req.get_method())
  local need_auth_flag = true


  for k, val in ipairs(conf.not_need_auth_http_methods) do
      if string.upper(val) == request_method then 
          need_auth_flag = false
      end
  end

  if need_auth_flag == true then
    if type(conf.key_names) ~= "table" then
      ngx.log(ngx.ERR, "[key-auth] no conf.key_names set, aborting plugin execution")
      return
    end

    .......

    set_header(constants.HEADERS.CONSUMER_ID, consumer.id)
    set_header(constants.HEADERS.CONSUMER_CUSTOM_ID, consumer.custom_id)
    set_header(constants.HEADERS.CONSUMER_USERNAME, consumer.username)
    ngx.ctx.authenticated_credential = credential
    ngx.ctx.authenticated_consumer = consumer
  end
end

return KeyAuthHandler

这里有一行代码是 local requestmethod = string.upper(ngx.req.getmethod()) 其中ngx.req.getmethod() 这一方法是使用了lua-nginx-module API 的函数,能获取到该次请求的Http动词方法。而后拿这一方法的值与配置的值想比较,看看是否须要身份认证才能往下执行业务侧的API。
保存好handler.lua 和 schema.lua这两个文件,去kong的配置文件中,找到custom
plugins一栏,将该控件设为可用:

而后咱们为以前方法为http POST时候不须要认证的Api加入该新的插件:
参考代码:

curl -i -X DELETE --url http://localhost:8001/apis/message_not_need_auth_api  
curl -i -X POST --url http://localhost:8001/apis/ --data 'name=message_applications_api' --data 'upstream_url=https://172.31.31.128:8183/' --data 'request_path=/applications'  
curl -i -X POST --url http://localhost:8001/apis/message_applications_api/plugins --data 'name=new-key-auth'

这样,咱们就为/applications 这一路径的restful Api加入了本身的认证逻辑,即POST /applications 这一注册应用的接口不须要身份认证,其余的例如DELETE /applications 等接口,须要进行身份认证。

6、使用Kong自带的插件进行Api请求的流控管理

许多须要对外开放的Api,都须要进行流控设置。Kong提供的插件中,就有这样的帮助restful Api进行流控功能的插件。kong的流控插件有分为调用次数限制的Rate Limiting插件和请求流量限制的Request Size Limiting插件。这里咱们介绍调用次数限制的Rate Limiting插件。
(1)Rate Limiting插件简介
Rate Limiting是对Http请求的次数,按照年,月,日,时,分,秒的粒度进行设置,能够设置多个粒度,但至少要设置一个。例如,咱们能够为一个API设置每分钟最多累计调用100次,每小时最多累计调用1000次,这样就须要设置config.minute=100 和 config.hour=1000。若是用户们1分钟内调用超过100次的时候,Kong则会返回Http 429调用过快的状态码,须要下一分钟才能调用。若是1小时累计超过1000次,则须要等待到下一小时(以该次调用的前999次的调用的时间差为准)

(2)为本身业务侧的restful Api加入Rate Limiting插件 选择须要进行流控限制的restful Api组,例如/applications,将其加上Rate Limiting插件。例如限制每分钟5000次调用:
参考命令:

curl -i -X POST --url http://localhost:8001/apis/message_applications_api/plugins/ --data "name=rate-limiting" --data "config.minute=5000"

Kong的api返回相似下面这样的提示,则表示成功:

当请求api的次数过快的时候,Kong会返回HTTP 429状态码提示:

@By_ljp_(PingLee)

(完)

相关文章
相关标签/搜索