本文举例来说明API签名,并有具体实现流程,规则弄会,一通百通。
本文先用一个故事举例,方便理解,然后对整个流程做了逐步分析和局部代码实现,最后把代码整合起来,想直接看整合后代码的可以直接去最底。

一、故事引入签名认证原理(不要纠结为什么吃饭这么麻烦- -!)

有家饭店,只对会员开放,小明在饭店注册会员。
        饭店给小明一个会员号"xiaoming"(签名中的ApiKey)并且永久有效。
        又给小明一个令牌(签名中的SecretKey),令牌内容是"abcd",并告诉小明令牌只能自己知道,不可以告诉别人,又告知令牌30天后失效,失效后可以再来申请一个新的令牌(依然30天有效期)。
        (饭店是知道小明的会员号和令牌的)
        这天,小明要在饭店点餐,主食:米饭,炒菜:土豆丝, 于是给饭店发送了点菜短信,短信内容可以有多种方案,具体内容如下(这里只写两个短信方案):
        方案一:

会员号:xiaoming
主食:米饭
炒菜:土豆丝
口令(signature):abcd(实际开发中,令牌abcd不会用于网络通讯中,而是把会员号,主食,炒菜三个键值对加密拼接,并用‘abcd’进行加密,具体实现下面会说明,这里先了解流程)

方案二:

会员号:小明
主食:米饭
炒菜:土豆丝
时间(timestamp):12点(假设偏差10分钟,如果饭店收到消息比11点50早或比12点10分晚,就认为是骗子)
随机码(nonce):7878(饭店每次都记录随机码,收到信息后看看随机码之前用过没,如果用过,就认为是骗子)
口令(signature):abcd(实际开发中,令牌abcd不会用于网络通讯中,而是会把上边5个键值对先加密,再拼接,再用‘abcd’加密作为口令,具体实现下面会说明,这里先了解流程)

饭店收到信息后核对无误,开始做饭。
        有人会有疑问,如果骗子随便写个随机码,刚好之前没用过,岂不是就蒙混过关了??注意一点,口令的生成和随机码有关系,所以只要骗子拿不到令牌(secretkey),就无法生成正确的口令。

二、准备(用户注册申请密钥)

服务器会返回两个key

AccessKey: 身份标识,唯一,类似ID,用户名什么的
SecretKey:密钥,只保存在客户端和服务器,不做网络传递,一般都有有效期

本文中

accesskey="ch_improve"
secretkey="abcd"

三、客户端生成签名

1.准备参数

需要传递的参数有:

{"accesskey": "ch_improve","name": "gaofushuai","city": "zhengzhou",
}

实际运用中,可以添加参数,例如

SignatureMethod="HmacSHA256"
timestamp=1572662767
method="POST"
nonce=7878

我以如下参数为例

{"accesskey": "ch_improve","name": "gaofushuai","city": "zhengzhou","SignatureMethod": "HmacSHA256","timestamp": 1572662767,"method": "POST","nonce": 7878
}
2.对参数进行排序并转为URL键值对格式字符串

首先需要对传递的参数按照键的字典升序进行排序,并得到URL键值对格式的字符串
SignatureMethod=HmacSHA256&accesskey=ch_improve&city=zhengzhou&method=POST&name=gaofushuai&nonce=7878&timestamp=1572662767

SignatureMethod=HmacSHA256&accesskey=ch_improve&city=zhengzhou&method=POST&name=gaofushuai&nonce=7878&timestamp=1572662767

python3代码实现
                (1)字典升序排序

args = {"accesskey": "ch_improve","name": "gaofushuai","city": "zhengzhou","SignatureMethod": "HmacSHA256","timestamp": 1572662767,"method": "POST","nonce": 7878
}args_order = sorted(args.items(), key=lambda x: x[0])

args_order的值如下

[('SignatureMethod', 'HmacSHA256'), ('accesskey', 'ch_improve'), ('city', 'zhengzhou'), ('method', 'POST'), ('name', 'gaofushuai'), ('nonce', 7878), ('timestamp', 1572662767)]

(2)转为URL字符串

import urllib.parseargs_str = urllib.parse.urlencode(args_order)

args_str的值如下,是一个长字符串

SignatureMethod=HmacSHA256&accesskey=ch_improve&city=zhengzhou&method=POST&name=gaofushuai&nonce=7878&timestamp=1572662767
3.使用密钥SecretKey对URL格式的字符串args_str进行加密获取签名

常用加密方法有MD5、SHA256等等,本文采用HmacSha256加密

import hmac
secretkey="abcd"
# 先把secretkey和args_str转为byte类型
b_secretkey = secretkey.encode('utf-8')
b_args_str = args_str.encode('utf-8')
# 用密钥对URL格式的参数进行hmacsha256加密
signature = hmac.new(b_secretkey, b_args_str, digestmod='sha256').hexdigest()

signature签名的值如下

3623d8070662392772d10952ea39c277518546006e6649f4ea358671e51e06f7

有些服务器要求把signature签名字符串全部转为大写,转不转大写看接口要求,本文就不再转大写了

4.在原有参数基础上添加signature签名参数,得到最新的参数
{"accesskey": "ch_improve","name": "gaofushuai","city": "zhengzhou","SignatureMethod": "HmacSHA256","timestamp": 1572662767,"method": "POST","nonce": 7878,"signature": "3623d8070662392772d10952ea39c277518546006e6649f4ea358671e51e06f7"
}
5.得到最终参数后,可以发送请求了,至于如何携带参数,基本有三种选择(URL字符串、请求头、请求体)

(1)URL键值对字符串

accesskey=ch_improve&name=gaofushuai&city=zhengzhou&
SignatureMethod=HmacSHA256&timestamp=1572662767&meth
od=POST&nonce=7878&signature=3623d8070662392772d10952
ea39c277518546006e6649f4ea358671e51e06f7

比如访问http://127.0.0.1:8888,那么url就是

http://127.0.0.1:8888/?accesskey=ch_improve&name=gaofushuai
&city=zhengzhou&SignatureMethod=HmacSHA256&timestamp=1572662767
&method=POST&nonce=7878&signature=3623d8070662392772d10952e
a39c277518546006e6649f4ea358671e51e06f7

(2)请求头中携带参数
                可以自定义一个字段,比如"MyArgs",值就使用字典参数的json格式字符串,如下

Myargs: {"accesskey": "ch_improve", "name": "gaofushuai", "city": "zhengzhou", "SignatureMethod": "HmacSHA256", "timestamp": 1572662767, "method": "POST", "nonce": 7878, "signature": "3623d8070662392772d10952ea39c277518546006e6649f4ea358671e51e06f7"}

(3)请求体中携带参数
                这个直接放入请求体就行,作为一般参数

四、服务器收到请求后验证

1.接受参数
{"accesskey": "ch_improve","name": "gaofushuai","city": "zhengzhou","SignatureMethod": "HmacSHA256","timestamp": 1572662767,"method": "POST","nonce": 7878,"signature": "3623d8070662392772d10952ea39c277518546006e6649f4ea358671e51e06f7"
}
2.检查时间戳timestamp(如果不使用时间戳作为参数,则跳过此步)

假如约定时间戳误差范围为10分钟,也就是600秒,根据接收到的时间戳1572662767计算出时间戳范围

1572662767-600  ~~  1572662767+600

获取服务器本地时间戳

import time
timestamp = time.time()

如果得到结果不在范围内,则拒绝访问

3.检查随机动态码nonce是否有效(如果不使用nonce作为参数,则跳过此步)

(1)nonce为客户端随机生成的验证码,当服务器接收到请求后,会把nonce存储到数据库中,一般使用redis,并设置一个有效期,一般和时间戳timestamp的失效时间保持一致,设为10分钟有效期。
        (2)当服务器接收到请求后,用请求中nonce(本文为7878)和redis中的nonce集合做比较,如果已经存在,则拒绝访问接口,只有当10分钟之内第一次使用7878这个动态码,才判定访问有效。

4.验证签名signature

对除了signature之外的所有参数进行升序URL格式转换拼接,得到字符串再用密钥secretkey(本文是‘abcd’)加密,得到signature2,和请求中的signature做比较判断请求是否合法。
        不一致则拒绝访问。

五、总结下生成签名认证请求参数生成的代码

import json  # 导入json
import urllib.parse  # 导入URL编译库
import hmac  # 导入HMAC加密库accesskey="ch_improve"
# 密钥,仅保存在客户端和服务端,不做网络传递,一般都有有效期,15天之类的
secretkey="abcd"# 准备参数
# 时间戳timestamp可以用 timestamp = int(time.time()) 生成
# nonce是随机生成的验证码,例如"7878", "k9i8e7"
args = {"accesskey": "ch_improve","name": "gaofushuai","city": "zhengzhou","SignatureMethod": "HmacSHA256","timestamp": 1572662767,"method": "POST","nonce": 7878
}# 对参数进行排序,按照键的字典升序排序
args_order = sorted(args.items(), key=lambda x: x[0])
# 得到args_order=[('SignatureMethod', 'HmacSHA256'), ('accesskey', 'ch_improve'), ('city', 'zhengzhou'), ('method', 'POST'), ('name', 'gaofushuai'), ('nonce', 7878), ('timestamp', 1572662767)]# 对排好序的元祖列表进行URL转换
args_str = urllib.parse.urlencode(args_order)
# 得到字符串SignatureMethod=HmacSHA256&accesskey=ch_improve&city=zhengzhou&method=POST&name=gaofushuai&nonce=7878&timestamp=1572662767# 对密钥和字符串进行byte转换
b_secretkey = secretkey.encode('utf-8')
b_args_str = args_str.encode('utf-8')# 用密钥abcd进行加密
signature = hmac.new(b_secretkey, b_args_str, digestmod='sha256').hexdigest()
# 得到签名3623d8070662392772d10952ea39c277518546006e6649f4ea358671e51e06f7# 把签名添加到请求参数中作为新的请求参数
{"accesskey": "ch_improve","name": "gaofushuai","city": "zhengzhou","SignatureMethod": "HmacSHA256","timestamp": 1572662767,"method": "POST","nonce": 7878,"signature": "3623d8070662392772d10952ea39c277518546006e6649f4ea358671e51e06f7"
}

最后希望大家给个赞吧

API密钥签名认证详解,包含timestamp+nonce方案BY:Zz Apollo相关推荐

  1. iOS 证书与签名 解惑详解

    iOS 证书与签名 解惑详解 分类: iPhone2012-06-06 19:57 9426人阅读 评论(1) 收藏 举报 iosxcodecryptographyappleiphone测试 目录(? ...

  2. 【Android签名机制详解】二:Android V1、V2、V3、V4签名方案

    前言 书接上回[Android签名机制详解]一:密码学入门,在了解了消息摘要.非对称加密.数字签名.数字证书的基本概念后,我们趁热打铁.直奔主题,讲解签名在Android中的实际应用. 基础知识 An ...

  3. JWT(Json web token)认证详解

    JWT(Json web token)认证详解 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该to ...

  4. MySQL权限授权认证详解

    MySQL权限授权认证详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MySQL权限系统介绍 1>.权限系统的作用是授予来自某个主机的某个用户可以查询.插入.修改.删 ...

  5. Android学习笔记——Android 签名机制详解

    Android 签名机制详解 近期由于工作需要在学习 Android 的签名机制,因为没有现成资料,只能通过开发者文档和阅读博客的方式对 Android 签名机制进行大致了解.过程中查阅到的资料相对零 ...

  6. 百度地图api定位的使用详解和返回错误码61的解决方案

    返回错误码61的解决方案我记不住了,我是看了官方demo改的,不过可以看下面的配置设置,应该可以解决,如果不能解决,可以评论或联系我 百度地图api定位的使用详解 1.获取密钥 官网 2.下载SDK, ...

  7. AndroidV1,V2,V3签名原理详解

    AndroidV1,V2,V3签名原理详解 签名校验流程 不同的签名版本之间的区别 V1签名保护机制 V2签名保护机制 V3签名保护机制 怎样判断使用的是哪种签名 参考链接: 签名校验流程 基础知识: ...

  8. Java API接口签名认证

    Java API接口签名认证 我们在进行程序开发的时候,一定会开发一些API接口,供他人访问.当然这些接口中有可能是开放的,也有可能是需要登录才能访问的,也就是需要Token鉴权成功后才可以访问的.那 ...

  9. linux 帐号 配置sftp_Linux 下sftp配置之密钥方式登录详解

    Linux下sftp配置之密钥方式登录 由于vsftp采用明文传输,用户名密码可通过抓包得到,为了安全性,需使用sftp,锁定目录且不允许sftp用户登到服务器.由于sftp使用的是ssh协议,需保证 ...

最新文章

  1. torch.full()简介
  2. Confluence 6 查看内容索引概要
  3. codeblocks如何watch数组
  4. ubuntu安装openssl命令
  5. 全球及中国橡胶助剂行业需求潜力及未来竞争态势研究报告2021版
  6. 产品经理们是如何越过 iOS 沙盒机制的?
  7. gnu java_【Java学习笔记】修饰符
  8. 解决由于Windows Installer造成的SAV安装失败的问题
  9. leetcode之回文链表
  10. H264编码质量屏幕截图
  11. python maketrans函数_python中maketrans
  12. 基于jQuery的AJAX和JSON的实例
  13. 为什么Linux7没有tree命令,如何在Centos7中添加Tree命令
  14. 编码规约学习——《阿里巴巴 Java 开发手册》
  15. BiliBili下载助手
  16. 企业微信客户端API分享微信朋友圈使用过程及总结
  17. 什么是 DataSource?什么又是 DruidDataSource?
  18. java数字转为大写_java 数字转大写汉字
  19. React报错:Too many re-renders
  20. 块级和图片的1px间隙

热门文章

  1. Unity插件-OSA(Optimized ScrollView Adapter)
  2. Qt的半透明方法总结
  3. mysql查询年龄段多少人_mysql中一张(居民)表按年龄段查询数据 shuaiflying
  4. 2022年华东师范大学计科考研复试机试题-详细题解
  5. Ants (POJNo.1852)--数据结构与算法刷题记录
  6. 会员收银系统颠覆传统门店经营模式
  7. 处理org.apache.hadoop.hbase.client.ScannerTimeoutException
  8. ChinaRen社区暴强回复
  9. 设圆半径为5,圆柱高为3,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。 编程序,用 scanf 输入数据,输出计算结果。输出时要有文字说明,取小数点后两位数字...
  10. 独立级联模型线性阈值模型