1、docker下安装Kong
1.1 创建一个自定义网络,用来允许容器之间的通信
dockernetworkcreatekong-net
1.2 通过docker-compose的方式安装
version: "3.7"
services:
# kong 管理界面
konga:
image: pantsel/konga
environment:
- "TOKEN_SECRET=51liveup.cn"
- "NODE_ENV=production"
ports:
- 1337:1337
networks:
- kong-net
depends_on:
- kong-database
# 数据库服务
kong-database:
image: postgres:9.6
ports:
- "5432:5432"
environment:
# 访问数据库的用户
- "POSTGRES_USER=kong"
- "POSTGRES_DB=kong"
- "POSTGRES_HOST_AUTH_METHOD=trust"
networks:
- kong-net
volumes:
# 同步时间
# - /etc/localtime:/etc/localtime:ro
# 数据库持久化目录
- ./data/postgresql:/var/lib/postgresql/data
kong:
# 镜像版本,目前最新
image: kong:latest
environment:
# 数据持久化方式,使用postgres数据库
- "KONG_DATABASE=postgres"
# 数据库容器名称,Kong连接数据时使用些名称
- "KONG_PG_HOST=kong-database"
# 数据库名称
- "KONG_CASSANDRA_CONTACT_POINTS=kong-database"
# 日志记录目录
- "KONG_PROXY_ACCESS_LOG=/dev/stdout"
- "KONG_ADMIN_ACCESS_LOG=/dev/stdout"
- "KONG_PROXY_ERROR_LOG=/dev/stderr"
- "KONG_ADMIN_ERROR_LOG=/dev/stderr"
# 暴露的端口
- "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl"
ports:
- 8000:8000
- 8443:8443
- 8001:8001
- 8444:8444
# 使用docker网络
networks:
- kong-net
# 依赖数据库服务
depends_on:
- kong-database
volumes:
# 数据库持久化目录
- ./data/kong:/data
networks:
kong-net:
external: true
1.3 执行docker-compose up 之后,会发现postgres连接不上,这个时候再初始化postgres数据库即可
dockerrun--rm\--network=kong-net\-e"KONG_DATABASE=postgres"\-e"KONG_PG_HOST=kong-database"\-e"KONG_CASSANDRA_CONTACT_POINTS=kong-database"\kong:latestkongmigrationsbootstrap
1.4 一定要在创建数据库容器之后,并且保持数据库的Docker容器在运行状态,再执行初始化数据库,数据库初始化成功后,再次使用docker-compose up -d 启动服务就可以了
1.5 安装成功之后,访问http://127.0.0.1:8001或者curl命令查看,出现如下效果即是安装成功
curl-ihttp://localhost:8001/
2、Konga可视化界面体验
2.1 创建登录账号
2.2 登录账号
2.3 连接docker环境中的kong
2.4 连接成功
3、Kong基础功能体验
3.1 以伊的家小程序商城列表数据为例,创建一个商品列表的路由服务
3.2.1以命令行方式创建一个Services
curl-i-XPOST\--urlhttp://localhost:8001/services/ \--data'name=kong-service'\--data'url=http://api-mall-admin.yidejia.com'
3.2.2 以Result Api方式创建一个Services
3.2.3 以Konga方式创建一个Services
3.3以命令行方式创建一个路由
curl-i-XPOST\--urlhttp://localhost:8001/services/kong-service/routes \--data'hosts[]=www.kong.com'
3.4 校验curl创建的服务跟路由
curl-i-XGET\--urlhttp://localhost:8000/api/admin/goods \--header'Host: www.kong.com'
出现如下效果即是创建成功
宿主机访问的话,需要额外增加hosts配置 127.0.0.1 www.kong.com
4、Kong插件体验
使用Kong自带的key-auth插件
4.1.1 以命令行方式使用一个插件
curl-i-XPOST\--urlhttp://localhost:8001/services/kong-service/plugins/ \--data'name=key-auth'
4.1.2 以Konga方式使用插件
4.1.3 查看访问效果
出现如下页面,即是插件生效
4.2.1以命令行方式创建一个消费者
curl-i-XPOST\--urlhttp://localhost:8001/consumers/ \--data"username=JyPony"
4.2.2 以Konga方式创建一个消费者
4.3.1以命令行方式为消费者创建一个key值
curl-i-XPOST\--urlhttp://localhost:8001/consumers/JyPony/key-auth/ \--data'key=123456'
4.3.2以Konga方式为消费者创建一个key值
4.4.1 再次访问http请求,出现如下效果,即是访问成功(Kong Error 报错消失了)
5、Kong插件自定义开发(Ascii参数校验示例)
5.1 基本插件模块和高级插件模块
5.2 创建项目,其中assci必须要插件名称
5.3 最简单的插件模块必须包含handler.lua文件跟schema.lua文件
handler.lua文件示例如下:
localipmatcher=require"resty.ipmatcher"localngx=ngxlocalkong=konglocalerror=errorlocalAsciiHandler={PRIORITY=990,VERSION="2.0.0",}localfunctionmatch_bin(list,binary_remote_addr)localip,err=ipmatcher.new(list)iferrthenreturnerror("failed to create a new ipmatcher instance: "..err)endlocalis_matchis_match,err=ip:match_bin(binary_remote_addr)iferrthenreturnerror("invalid binary ip address: "..err)endreturnis_matchend--判断table是否为空localfunctionisTableEmpty(t)returnt==nilornext(t)==nilend--两个table合并localfunctionunion(table1,table2)fork,vinpairs(table2)dotable1[k]=vendreturntable1end--检验请求的sign签名是否正确--params:传入的参数值组成的table--secret:项目secret,根据key找到secretlocalfunctionsignCheck(params,secret,binary_remote_addr,allow,deny)ifallowand#allow > 0 thenlocalallowed=match_bin(allow,binary_remote_addr)ifallowedthenlocalmess="白名单ip"returntrue,messendendifdenyand#deny > 0 thenlocalblocked=match_bin(deny,binary_remote_addr)ifblockedthenlocalmess="黑名单ip"returnfalse,messendend--判断参数是否为空,为空报异常ifisTableEmpty(params)thenlocalmess="参数为空"returnfalse,messendifsecret==nilthenlocalmess="私钥为空"returnfalse,messend--判断是否有签名参数localsign=params["sign"]ifsign==nilthenlocalmess="签名参数为空"returnfalse,messend--是否存在时间戳的参数localtimestamp=params["time"]iftimestamp==nilthenlocalmess="时间戳参数为空"returnfalse,messend--时间戳过期时间校验,10秒钟校验localnow_mill=ngx.now()*1000--毫秒级ifnow_mill-(timestamp*1000)>10000thenlocalmess="链接过期"returnfalse,messendlocalkeys,tmp={}, {}--提出所有的键名并按字符顺序排序fork,_inpairs(params)doifk~="sign"thenkeys[#keys + 1] = kendendtable.sort(keys)--根据排序好的键名依次读取值并拼接字符串成key=value&key=valuefor_,kinpairs(keys)doiftype(params[k])=="string"ortype(params[k])=="number"thentmp[#tmp + 1] = k .. "=" .. tostring(params[k])endend--将salt添加到最后,计算正确的签名sign值并与传入的sign签名对比,localsignChar=table.concat(tmp,"&") ..secretlocalrightSign=ngx.md5(signChar)ifsign~=rightSignthen--返回错误信息localmess="sign error: sign,"..sign.."right sign:"..rightSign.." sign_char:"..signChar--localmess="sign error: sign,"..sign.."right sign:"..rightSign.." sign_char:"..table.concat(tmp,"&")returnfalse,messendreturntrueendfunctionAsciiHandler:access(conf)localbinary_remote_addr=ngx.var.binary_remote_addrifnotbinary_remote_addrthenreturnkong.response.error(403,"Cannot identify the client IP address, unix domain sockets are not supported.")end--获取参数localparams={}localget_args=ngx.req.get_uri_args();ngx.req.read_body()localpost_args=ngx.req.get_post_args();union(params,get_args)union(params,post_args)--校验secretlocalsecret=conf.secretlocalcheckResult,mess=signCheck(params,secret,binary_remote_addr,conf.allow,conf.deny)ifnotcheckResultthenreturnkong.response.error(403,mess)--returnkong.response.exit(403, {message=mess})endendreturnAsciiHandler
schema.lua文件示例如下:
localtypedefs=require"kong.db.schema.typedefs"return{name="ascii",fields={{consumer=typedefs.no_consumer},{protocols=typedefs.protocols_http},{config={type="record",fields={{allow={type="array",elements=typedefs.ip_or_cidr, }, },{deny={type="array",elements=typedefs.ip_or_cidr, }, },{secret={type="string",default="secret",required=true, }, }, },shorthands={--deprecatedforms,toberemovedinKong3.0{blacklist=function(value)return{deny=value}end},{whitelist=function(value)return{allow=value}end}, }, }, }, },entity_checks={{at_least_one_of={"config.allow","config.deny","config.secret"}, }, },}
5.4 hadler.lua规范
5.5 schema.lua规范
5.6 docker插件位置存放跟配置
5.6.1 去到docker-compose中配置的kong共享目录./data, 将插件储存在当前位置
5.6.2 引入插件位置,并关联插件
sudodocker exec-it-uroot kong_kong_1bashvi/etc/kong/kong.conf# 配置信息plugins=bundled,asciilua_package_path=/data/?.lua;;
其中, /data/?.lua是你插件的路径,;;保持默认,意思是引入原先插件的位置
5.6.3 进入到kong容器中,发布配置并重启
kongpreparekongreload
5.6.4 去到Konga查看效果
5.6.5 配置并使用插件
出现如下效果说明创建成功
输入正确的签名请求地址
http://www.kong.com:8000/api/admin/goods?sign=3f60fac9ff6026e6d283d4ea8709ee46&time=1599299584&apikey=123456
5.7 php签名校验方法实现(Ascii)
$val) {$str.=$k.'='.$val.'&'; }$strs=rtrim($str,'&');return$strs; } }returnfalse;}$data=['apiKey'=>'123456','time'=>time()];$str='secret';$s_data=asc_sort($data);echo$s_data."
";$sign=md5($s_data.$str);echo$sign."
";echotime();
6、参考资料
https://github.com/Kong/kong
https://github.com/qianyugang/kong-docs-cn
配置详解
https://www.cnblogs.com/SummerinShire/p/6628021.html
https://docs.konghq.com/1.2.x/getting-started/configuring-a-service/
https://www.cnblogs.com/zhoujie/p/kong3.html