题记----接上篇博文。
这篇博文主要要讲的是,根据腾讯官方开发者文档进行公众号开发者基本配置后,出现的token验证无法通过的问题,在此我将叙述整个懵逼及思考的过程。
我在按照文档对相关配置完成操作后,提交配置却出现“Token验证错误”的提示,一脸懵逼的我反复查看自己的配置和代码,并与官方文档一字一句的进行比较,没错啊。
在排除自己操作及编写代码出错的可能性之后,我对代码进行了断点检查。发现从微信公众平台上提交的数据signature,timestamp,nonce,echostr,token已经到达服务器端,那么就是代码逻辑或者代码语法的错误。
微信公众号开发基本配置的token验证过程是这样的:从网页端提取signature,timestamp,nonce,echostr,token字段的数据,其中token是自定义字段,timestamp是时间戳。将token,timestamp,nonce放入一个空列表中,并对其进行哈希加密。最后将加密完成的hashcode与signature进行对比,如一致,则返回echostr表示通过,若不一致则返回空。
在对代码进行断点检查过程中,我发现各项字段的数值都正常提交,可是最后的hashcode与signature就是不一致,如下图所示:
通过对此问题的查询,基本有了三种思路:1、代码执行时间差异导致时间戳不一致的,致使hashcode和signature不同;2、在网页几次更改token,网页缓存存储的token与服务器端的token不一致;3、哈希加密算法有问题。
确定了问题之后就开始一个一个排查,1、时间戳的问题,因为时间戳是直接从网页提交给服务器端的,而不是两边分别抓取时间,所以不存在时间不一致的问题;2、网页缓存token值的问题,清空缓存而且重新使用新的浏览器提交数据均出现错误,所以暂时排除网页缓存导致的token不一致的问题;
3、哈希加密算法的问题,因为我自己对哈希加密算法并不是了解很多,所以最开始是完全相信官方文档中的算法表述,丝毫没有产生怀疑,这也是导致我花费了大量的时间去排查除了这个问题的其他问题的最主要的原因。但是当我回过头来仔细查看官方文档给出的哈希算法,并查阅了python中哈希算法的语法时,我发现了问题。
下图为官方文档给出的哈希算法部分
其中map()函数占了其中一行,通过查阅python文档,
map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
语法
map() 函数语法:
map(function, iterable, ...)
参数:
function -- 函数
iterable -- 一个或多个序列
代码示例
>>>def square(x) : # 计算平方数
... return x ** 2
...
>>> map(square, [1,2,3,4,5]) # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]
# 提供了两个列表,对相同位置的列表数据进行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]
通过以上示例,其实已经可以明白了,python3 版本以前的 map() 函数对其中的参数进行执行后,输出的是一个新的列表,与原先的列表已经毫无关系,(在python3以后的版本里,map()函数返回是一个迭代器,所以它其实是不可调用的)也就是说官方文档中
map(sha1.update,list)
这句代码其实是生成了一个新的列表,原来的list列表内的内容并没有改变,违背了哈希加密的初衷,所以最后导致最终的 hashcode != signature,导致token验证是中通过不了。
通过查找相关资料,我已将代码修改为如下,修改过后即可成功通过token验证,代码如下:
list = [token,timestamp,nonce]
list.sort()
sha1 = hashlib.sha1()
sha1.update(list[0].encode("utf-8"))
sha1.update(list[1].encode("utf-8"))
sha1.update(list[2].encode("utf-8"))
hashcode = sha1.hexdigest() #获取加密串
至此,通过今天对微信公众号开发的学习,着实深切的体会到,没有什么权威是不会错的,遇到问题后冷静分析,大胆猜测,仔细探究,遇到权威也要大胆的去质疑,只有大胆的质疑才会使自己不局限于狭隘的技术层次,从而向更高的境界跃进。
高勇
2018.10.21凌晨