因为微信官方没有提供相关的代码Demo,所以使用rails框架开发微信公众号应用的小伙伴都会遇到一些不可避免的问题,比如消息验证、加密解密以及微信支付开发的一些坑。
本篇文章就基于我的一些开发经验,讲解:
- 微信消息验证
- 非加密xml消息的解析
1. 验证微信服务器消息的真实性
为什么要验证:避免恶意消息攻击
微信服务器发送至开发者填写好的url消息,会携带下列参数:
- signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
- timestamp 时间戳
- nonce 随机数
- echostr 随机字符串
官方给出的验证思路是:1)将token、timestamp、nonce三个参数进行字典序排序 2)将三个参数字符串拼接成一个字符串进行sha1加密 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
这里给出我用rails框架的消息验证示例:
def check_signature(signature, timestamp, nonce)
token = 'xxxxxxxxxxxxxx' # 公众号后台配置好的token
arr = [token, timestamp, nonce]
arr = arr.sort
text = ''
arr.each {|element| text += element}
(Digest::SHA1.hexdigest(text)==signature) ? true : false # 验证消息
end
2. 非加密xml消息的解析
微信服务器会将xml格式的消息内容发送至配置好的消息接收url,需要通过以下方法解析对应的xml消息:
content = Nokogiri::XML(request.body.read)
其中,request.body.read
会读取微信服务器发送过来的消息消息,Nokogiri::XML
则将读取到的消息转化为xml格式的对象。
以文本消息为例,我们来看看如果和去xml标签的内容:
<xml> <ToUserName>< ![CDATA[toUser] ]></ToUserName> <FromUserName>< ![CDATA[fromUser] ]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType>< ![CDATA[text] ]></MsgType> <Content>< ![CDATA[this is a test] ]></Content> <MsgId>1234567890123456</MsgId> </xml>
获取FromUserName
:
username = content.at_css('FromUserName').children.text
至此,我们简单的了解了如果在rails框架中验证微信消息的真实性以及解析对应的xml消息。