API接口有多种认证方式,例如
基础认证(用户名/密码)
、apikey(秘钥)
、token(令牌)
、JWT(令牌)
、signature(签名)
等。非对称签名认证应用广泛,接下来从客户端到服务端简单实现非对称签名,签名算法采用HMAC SHA256
。
数字签名
数字签名技术是将摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用HASH函数对收到的原文产生一个摘要信息,与解密的摘要信息对比。如果相同,则说明收到的信息是完整的,否则说明信息被修改,因此数字签名能保证信息传输过程中完整性、提供信息发送者的身份认证和不可抵赖性。可以用数字签名来做API认证。
签名过程
使用随机函数生成公私钥对,例如
1 | 公钥: "8thcm24furn0likp" |
选择合适的摘要签名信息,可以采用当前时间
1 | 摘要信息: "date: 2019-10-21 10:58:58" |
将摘要信息用HMAC SHA256
进程签名,并对原始的二进制数据进行Base64编码
,得到签名值
1 | 签名值: "33xn46YabD78N372yw+WV4NvNSTRrRbmAV7mcz0vDUQ=" |
客户端header
组装,x-api-key
用来传输公钥,date
用来传输摘要信息,authorization
用来传输完整的签名信息
1 | 'x-api-key': '8thcm24furn0likp', |
签名实现
python
可以基于HTTPSignatureAuth
来实现
1 | # -*- coding: utf-8 -*- |
如果是Kong的上游请求需要进行签名认证,可以基于openssl.hmac
和ngx
模块实现
1 | local BasePlugin = require "kong.plugins.base_plugin" |
验证签名
首先,服务端通过客户端请求传输的header
信息,获取摘要信息、签名值、公钥并找到本地对应的私钥,然后使用同样的算法用私钥对摘要信息进行签名,最后通过对比传输的签名值和本地签名值是否一致,来判断认证的有效性。
基于Iris框架的实现
1 | // SignatureAuth 判断签名是否有效 |
给需要认证的API添加拦截器
1 | func before(ctx iris.Context) { |
测试,未通过签名认证认返回信息
1 | { |