[号外]微信公众平台开发---消息体签名及加解密

  离刚开始做微信开发到现在已经两个月了,因为被分配了另外一个任务,所以微信的开发就先放到了一遍。

  在小公司便是如此,只有自己一个人做开发,所以哪里需要就要先转到哪一块。其实想想自己也没什么太好的理由说留在这个公司,想想也就是工作比较放松点,老板人还可以,项目上也催的不紧,孩子还小家里有点事了可以随时请假回家,这次也是家里父亲和小孩都住院了请了半个月假刚过来。

  闲话不多说,先说下微信开发的博客,微信开发也算完成了一部分,因为没有完成,所以之前的『微信公众平台开发(一)---接口介绍及配置』起了个头便一直没写,目前打算是等手头这边的工作完了把大致的功能都写的差不多了再继续写。

  这次来了之后看到微信接口增加了“消息体签名及加解密”这块,于是抽了一点时间把原来的接口的消息加密模式改成安全模式。因为微信接口已经提供了加/解密的实现,所以修改起来也是极其的简单了,下面就简单说下  验证微信签名以及对微信消息的加/解密。

  首先,在开发者首次提交验证申请时,微信服务器将发送GET请求到填写的URL上,并且带上四个参数(signature、timestamp、nonce、echostr),开发者通过对签名(即signature)的效验,来判断此条消息的真实性。

  开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。

  修改我们上次创建的WeixinService.cs  

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.ServiceModel;
 6 using System.ServiceModel.Activation;
 7 using System.ServiceModel.Web;
 8 using System.Web.Security;
 9 using System.Runtime.Serialization;
10 using System.IO;
11 using System.Text;
12 using WeiXinModel;
13 using WeiXinRestWCF.BLL;
14
15 namespace WeiXinRestWCF
16 {
17     [ServiceContract]
18     [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
19     [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
20     public class WeixinService
21     {
22         /// <summary>
23         /// 验证微信签名
24         /// </summary>
25         /// * 将token、timestamp、nonce三个参数进行字典序排序
26         /// * 将三个参数字符串拼接成一个字符串进行sha1加密
27         /// * 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信。
28         /// <returns></returns>
29         [OperationContract]
30         [WebGet(UriTemplate = "API?signature={signature}&timestamp={timestamp}&nonce={nonce}&echostr={echostr}", ResponseFormat = WebMessageFormat.Json)]
31         public Stream CheckSignature(string signature, string timestamp, string nonce, string echostr)
32         {
33             string outstr = string.Empty;
34             if (SignatureHelper.CheckSignature(signature, timestamp, nonce))
35             {
36                 if (!String.IsNullOrEmpty(echostr))
37                 {
38                     outstr = echostr;
39                 }
40             }
41             byte[] resultBytes = Encoding.UTF8.GetBytes(outstr);
42             WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
43             return new MemoryStream(resultBytes);
44         }
45
46     }
47
48 }

  在上面的代码中,我们添加了一个WebGet来处理微信发送过来的签名验证GET请求,在UriTemplate中我们添加传入的4个参数,注意{}内的参数字符与方法体的参数名称大小写对应。

  需要着重提示的一点就是wcf的返回结果默认是json或xml这两种格式之一,而对于微信服务器需要我们返回的结果是文本型的,所以在这里我们必须把方法体返回的结果设置为Stream类型,并在方法体内设置  WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";将需要返回的结果字符串写进MemoryStream中,以此达到我们想到达到的目的。

  SignatureHelper.CheckSignature对应的实现:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.IO;
 6 using System.Web.Security;
 7 using System.Text;
 8
 9 namespace WeiXinRestWCF.BLL
10 {
11     public class SignatureHelper
12     {
13         //检验signature判断真实性
14         public static bool CheckSignature(string signature, string timestamp, string nonce)
15         {
16             bool ischeck = false;
17             string[] ArrTmp = { DeveloperInfo.ServerToken, timestamp, nonce };
18             Array.Sort(ArrTmp);
19             string tmpStr = string.Join("", ArrTmp);
20             tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
21             tmpStr = tmpStr.ToLower();
22             string outstr = string.Empty;
23             if (tmpStr == signature)
24             {
25                 ischeck = true;
26             }
27             return ischeck;
28         }
29     }
30 }

  这样,我们就完成了签名验证的过程。接下来我们处理来自微信用户的消息。

  当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。

  (每次开发者接收用户消息的时候,微信也都会带上前面三个参数(signature、timestamp、nonce)访问开发者设置的URL,开发者依然通过对签名的效验判断此条消息的真实性。PS:特别注意同事传递的另外一个的参数:msg_signature,这个也是对加密的消息体进行解密时的一个重要参数)

  微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次

  假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

  对于接收到的微信消息我们这样处理:

  在WeixinService.cs中添加下面的代码以对微信服务器的POST请求作出回应:

 1         /// <summary>
 2         /// 接收微信传递来的消息
 3         /// </summary>
 4         /// <param name="xmlMessage">传递的消息</param>
 5         /// <returns></returns>
 6         [OperationContract]
 7         [WebInvoke(Method = "POST", UriTemplate = "API?signature={signature}&timestamp={timestamp}&nonce={nonce}&msg_signature={msg_signature}", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
 8         //注意上面我们的UriTemplate中url参数列表内包含了msg_signature参数
 9         public Stream ReciveTextMessge(Stream xmlMessage, string signature, string timestamp, string nonce, string msg_signature)
10         {
11             //此处依然需要验证消息请求来源是否为微信服务器
12             if (!SignatureHelper.CheckSignature(signature, timestamp, nonce))
13             {
14                 return null;
15             }
16             WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(DeveloperInfo.ServerToken, DeveloperInfo.EncodingAESKey, DeveloperInfo.AppId);
17             //我这里创建了DeveloperInfo类,其中存放着开发者相关的信息,如 public const string AppId = "*************";
18             int ret = 0;
19
20             double createTime = Math.Truncate(DateTime.UtcNow.Subtract(DateTime.Parse("1970-1-1")).TotalSeconds);
21             StreamReader reader = new StreamReader(xmlMessage);
22             //[密文]收到的消息
23             string incptmsg = reader.ReadToEnd();
24             //[明文]收到的消息
25             string Recive = string.Empty;
26
27             //在对收到的用户消息进行处理之前进行解密(只在消息内容不为空的时候)
28             if (!string.IsNullOrEmpty(incptmsg))
29             {
30                 ret = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, incptmsg, ref Recive);//注意,此处使用的是msg_signature
31             }
32             ReciveHandler.LogReciveMsg(Recive);//这里记录所有收到的消息到DataBase中
33             //[明文]回复的消息
34             string Reply = ReplyHandler.GetReply(Recive);//ReplyHandler.GetReply方法会对受到的消息进行处理,并返回对应回复消息的字符串
35             //[密文]回复的消息
36             string outcpt = string.Empty;
37             //在此对回复的消息体进行加密(只在消息内容不为空的时候)
38             if (!string.IsNullOrEmpty(Reply))
39             {
40                 ret = wxcpt.EncryptMsg(Reply, timestamp, nonce, ref outcpt);
41             }
42
43             byte[] resultBytes = Encoding.UTF8.GetBytes(outcpt);
44             WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
45
46             Log("这里收到的一条POST信息,当前时间:" + DateTime.Now.ToString() + "\r\n" + "标准时间间隔秒数:" + createTime + "\r\n" + Recive + "\r\n\r\n" + "服务器返回信息为:" + Reply);
47             return new MemoryStream(resultBytes);
48         }                        

  微信消息体的加密解密代码可以参照API文档中提供的Demo,下载地址:http://mp.weixin.qq.com/wiki/downloads/SampleCode.zip

  结果如下:

  

  

  

  

   暂时先写到这里。To be continued...

时间: 2024-10-24 19:24:04

[号外]微信公众平台开发---消息体签名及加解密的相关文章

微信消息体签名及加解密功能详细解析以及.net实现

原文:微信消息体签名及加解密功能详细解析以及.net实现 前言 微信消息体签名及加密功能已上线,明文传输确实存在安全风险,鉴于微信的用户范围使用之广泛,必定会成为众矢之的.所以大家还是尽快接入安全模式为好.仔细阅读官方接入指南,发现这次安全升级只是涉及到用户在微信对话窗口中与公众好消息交互,所以此次升级还是比较简单的.下面为大家一一道来. 一.功能解析 微信消息体签名及加密功能已上线,出于安全考虑,强烈建议您尽快接入消息加密功能,消除安全风险.详见公告.公众平台接口调试工具已经全面支持消息体加密

C#微信公众号开发系列教程三(消息体签名及加解密)

  C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南)    距离上一篇博文已经半个月了,本来打算每两天更新一次的,但可怜苦逼码农无日无夜的加班.第一篇博文发表后,博文视点的编辑就找到我,问我想不想出版这个系列,我当时瞬间就想到了王大锤的独白,想想真的是有点小激动,后面按照那边的要求,提交了申请书,也提交了目录,可惜文笔不行,再加上最近太忙,样稿一直没有给他,感觉挺愧疚了.真心希望能帮一下迷茫的

微信公众平台消息体签名及加解密实例(Java)

前言: 最近在研究微信公众平台的开发,玩得不亦乐乎.基本的回复功能已经实现了,而且回复用到了图灵机器人的接口.其实图灵机器人已经有微信接口可以直接调用.如果项目的需要,想要做个性化需求的话,用这种方式是行不通的.我现在的解决方案是,我开发的应用A作为中间层,连接微信接口与图灵机器人接口.有点扯远了,如题,微信官方为了更高的安全性,10月份推出了消息体签名验证.网上关于此项的实例不多,其实根据官方的例子,重新封装一下,就可以了. 一.准备工作: 1.已申请了相关的订阅号或者服务号(可以用虚拟器,具

微信公众平台开发——关于网页签名那些事

如果从微信公众号通过菜单的响应类型view来打开网页,首先这个网页必须要有正常的域名,不允许是ip地址.如果这个网页没有备案或者说这个域名没有备案,那么进入这个网页之前微信会先弹出一个网页提示我们是继续访问或者使用原网页打开,这是非常烦人的,因为每次你用a标签或者href来跳转网页时都会这样.最简单的办法就是使用备案的域名绑定你的服务器上网页地址.如果你实在觉得备案麻烦,那么你也可以这样这样做: 使用微信对网页授权的办法进入页面.可以先了解https://mp.weixin.qq.com/wik

微信公众平台开发之对加密模式的解密

消息加密模式有三种,如下图: 在明文模式下我们不需要解密,但如果是加密模式提交的,我们要对得到的数据进行解密才能使用. 一.首先要到官方网站下载示例文件. 点这里下载... 1.拷贝包src.com.qq.weixin.mp.aes下的java类 2.拷贝jar包:commons-codec-1.9.jar 3.官方说明: 提供接收和推送给公众平台消息的加解密接口(UTF8编码的字符串).            第三方回复加密消息给公众平台            第三方收到公众平台发送的消息,验

ASP.NET MVC5+EF6+EasyUI 后台管理系统(73)-微信公众平台开发-消息管理

前言 回顾上一节,我们熟悉的了解了消息的请求和响应,这一节我们来建立数据库的表,表的设计蛮复杂 你也可以按自己所分析的情形结构来建表 必须非常熟悉表的结果才能运用这张表,这表表的情形涵盖比较多 思维导图 我这个人比较喜欢用思维导图来分析和表达一些模型: 表结构 根据思维导图,我们可以建立的表可以是3张表:消息表,规则表,类型表 消息表:实际的消息 规则表:文本.图文.语音等 类型表:文本.图文.语音(默认回复,订阅回复) 也可以是两张表:规制表,消息表(+一个类型字段) 我这里只设计一张表:消息

微信公众平台开发接口PHP SDK完整版

原文:微信公众平台开发接口PHP SDK完整版 官方提供的SDK只有一个文本消息功能,我们将所有消息的消息类型及事件响应都整理了进来,并且加入日志记录,代码如下: 更新日志: 2013-01-01 版本1.02014-03-15 增加图片.视频.语音的内容回复2014-04-09 增加菜单链接事件2014-04-10 修改文本回复的判定方法2014-05-20 增加高级群发消息通知事件2014-05-26 增加多客服消息及多客服的判定方法2014-05-27 修改自动回复判定方式2014-06-

20160170002 微信公众平台开发接入指南

参考地址: http://mp.weixin.qq.com/wiki/17/2d4265491f12608cd170a95559800f2d.html 接入指南 目录 1 概述 2 第一步:填写服务器配置 3 第二步:验证服务器地址的有效性 4 第三步:依据接口文档实现业务逻辑 概述 接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 2.验证服务器地址的有效性 3.依据接口文档实现业务逻辑 下面详细介绍这3个步骤. 第一步:填写服务器配置 登录微信公众平台官网后,在公众平台

微信公众平台开发教程--方培工作室,PHP语言版本

准备工作 微信公众平台的注册 介绍如何注册一个微信公众账号. 入门教程 微信公众平台开发入门教程 内容:1.申请SAE作为服务器; 2.启用开发模式; 3.微信公众平台PHP SDK; 4.接收发送消息类型解析; 5.微信公众平台开发模式原理; 6.快速开发天气预报功能. 入门教程是下面所有教程的基础. 基础接口 微信公众平台开发(2) 天气预报 介绍了使用中国天气网气象数据,实现微信上的天气预报功能. 微信公众平台开发(3) 中英翻译 介绍了使用有道翻译的接口,在微信公众平台上,开发中英互译的