数码控科技猎奇Iphone动漫星座游戏电竞lolcosplay王者荣耀攻略allcnewsBLOGNEWSBLOGASKBLOGBLOGZSK全部技术问答问答技术问答it问答代码软件新闻开发博客电脑/网络手机/数码笔记本电脑互联网操作系统软件硬件编程开发360产品资源分享电脑知识文档中心IT全部全部分类全部分类技术牛文全部分类教程最新网页制作cms教程平面设计媒体动画操作系统网站运营网络安全服务器教程数据库工具网络安全软件教学vbscript正则表达式javascript批处理更多»编程更新教程更新游戏更新allitnewsJava新闻网络医疗信息化安全创业站长电商科技访谈域名会议专栏创业动态融资创投创业学院 / 产品经理创业公司人物访谈营销开发数据库服务器系统虚拟化云计算嵌入式移动开发作业作业1常见软件all电脑网络手机数码生活游戏体育运动明星影音休闲爱好文化艺术社会民生教育科学医疗健康金融管理情感社交地区其他电脑互联网软件硬件编程开发360相关产品手机平板其他电子产品摄影器材360硬件通讯智能设备购物时尚生活常识美容塑身服装服饰出行旅游交通汽车购房置业家居装修美食烹饪单机电脑游戏网页游戏电视游戏桌游棋牌游戏手机游戏小游戏掌机游戏客户端游戏集体游戏其他游戏体育赛事篮球足球其他运动球类运动赛车健身运动运动用品影视娱乐人物音乐动漫摄影摄像收藏宠物幽默搞笑起名花鸟鱼虫茶艺彩票星座占卜书画美术舞蹈小说图书器乐声乐小品相声戏剧戏曲手工艺品历史话题时事政治就业职场军事国防节日风俗法律法规宗教礼仪礼节自然灾害360维权社会人物升学入学人文社科外语资格考试公务员留学出国家庭教育学习方法语文物理生物工程学农业数学化学健康知识心理健康孕育早教内科外科妇产科儿科皮肤科五官科男科整形中医药品传染科其他疾病医院两性肿瘤科创业投资企业管理财务税务银行股票金融理财基金债券保险贸易商务文书国民经济爱情婚姻家庭烦恼北京上海重庆天津黑龙江吉林辽宁河北内蒙古山西陕西宁夏甘肃青海新疆西藏四川贵州云南河南湖北湖南山东江苏浙江安徽江西福建广东广西海南香港澳门台湾海外地区

.NET微信小程序用户数据的签名验证和解密代码

来源:脚本之家  责任编辑:小易  

微信小程序时下大热,抱着学习的心态了解了一下,目前没有搜到完整的.NET用户数据签名验证和解密代码,于是就写了一点。

简单使用方法:

1、客户端调用wx.getUserInfo方法,服务端创建WeChatLoginInfo类的实例接收客户端发来的数据;
2、服务端新建WeChatAppDecrypt类的实例,初始化此类时需传入appId与AppSecret用于验证;
3、调用WeChatAppDecrypt类中的Decrypt方法,传入步骤1中获取的WechatLoginInfo实例;
4、得到WechatUserInfo类的实例,其中就是解密好的数据。

话不多说,注释比较详尽,感兴趣的朋友可以参考。

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using System.Security.Cryptography;
using System.Text;
 
namespace BroadSky.WeChatAppDecrypt
{
  /// <summary>
  /// 处理微信小程序用户数据的签名验证和解密
  /// </summary>
  public class WeChatAppDecrypt
  {
    private string appId;
    private string appSecret;
 
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="appId">应用程序的AppId</param>
    /// <param name="appSecret">应用程序的AppSecret</param>
    public WeChatAppDecrypt(string appId, string appSecret)
    {
      this.appId = appId;
      this.appSecret = appSecret;
      return;
    }
 
    /// <summary>
    /// 获取OpenId和SessionKey的Json数据包
    /// </summary>
    /// <param name="code">客户端发来的code</param>
    /// <returns>Json数据包</returns>
    private string GetOpenIdAndSessionKeyString(string code)
    {
      string temp = "https://api.weixin.qq.com/sns/jscode2session?" + 
        "appid=" + appId
        + "&secret=" + appSecret
        + "&js_code=" + code 
        + "&grant_type=authorization_code";
 
      return GetResponse(temp);
 
    }
 
    /// <summary>
    /// 反序列化包含OpenId和SessionKey的Json数据包
    /// </summary>
    /// <param name="code">Json数据包</param>
    /// <returns>包含OpenId和SessionKey的类</returns>
    public OpenIdAndSessionKey DecodeOpenIdAndSessionKey(WechatLoginInfo loginInfo)
    {
      OpenIdAndSessionKey oiask = JsonConvert.DeserializeObject<OpenIdAndSessionKey>(GetOpenIdAndSessionKeyString(loginInfo.code));
      if (!String.IsNullOrEmpty(oiask.errcode))
        return null;
      return oiask;
    }
 
    /// <summary>
    /// 根据微信小程序平台提供的签名验证算法验证用户发来的数据是否有效
    /// </summary>
    /// <param name="rawData">公开的用户资料</param>
    /// <param name="signature">公开资料携带的签名信息</param>
    /// <param name="sessionKey">从服务端获取的SessionKey</param>
    /// <returns>True:资料有效,False:资料无效</returns>
    public bool VaildateUserInfo(string rawData, string signature, string sessionKey)
    {
      //创建SHA1签名类
      SHA1 sha1 = new SHA1CryptoServiceProvider();
      //编码用于SHA1验证的源数据
      byte[] source = Encoding.UTF8.GetBytes(rawData + sessionKey);
      //生成签名
      byte[] target = sha1.ComputeHash(source);
      //转化为string类型,注意此处转化后是中间带短横杠的大写字母,需要剔除横杠转小写字母
      string result = BitConverter.ToString(target).Replace("-","").ToLower();
      //比对,输出验证结果
      return signature == result;
    }
 
    /// <summary>
    /// 根据微信小程序平台提供的签名验证算法验证用户发来的数据是否有效
    /// </summary>
    /// <param name="loginInfo">登陆信息</param>
    /// <param name="sessionKey">从服务端获取的SessionKey</param>
    /// <returns>True:资料有效,False:资料无效</returns>
    public bool VaildateUserInfo(WechatLoginInfo loginInfo, string sessionKey)
    {
      return VaildateUserInfo(loginInfo.rawData, loginInfo.signature, sessionKey);
    }
 
    /// <summary>
    /// 根据微信小程序平台提供的签名验证算法验证用户发来的数据是否有效
    /// </summary>
    /// <param name="loginInfo">登陆信息</param>
    /// <param name="idAndKey">包含OpenId和SessionKey的类</param>
    /// <returns>True:资料有效,False:资料无效</returns>
    public bool VaildateUserInfo(WechatLoginInfo loginInfo, OpenIdAndSessionKey idAndKey)
    {
      return VaildateUserInfo(loginInfo, idAndKey.session_key);
    }
 
    /// <summary>
    /// 根据微信小程序平台提供的解密算法解密数据
    /// </summary>
    /// <param name="encryptedData">加密数据</param>
    /// <param name="iv">初始向量</param>
    /// <param name="sessionKey">从服务端获取的SessionKey</param>
    /// <returns></returns>
    public WechatUserInfo Decrypt(string encryptedData, string iv, string sessionKey)
    {
      WechatUserInfo userInfo;
      //创建解密器生成工具实例
      AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
      //设置解密器参数
      aes.Mode = CipherMode.CBC;
      aes.BlockSize = 128;
      aes.Padding = PaddingMode.PKCS7;
      //格式化待处理字符串
      byte[] byte_encryptedData = Convert.FromBase64String(encryptedData);
      byte[] byte_iv = Convert.FromBase64String(iv);
      byte[] byte_sessionKey = Convert.FromBase64String(sessionKey);
 
      aes.IV = byte_iv;
      aes.Key = byte_sessionKey;
      //根据设置好的数据生成解密器实例
      ICryptoTransform transform = aes.CreateDecryptor();
      
      //解密
      byte [] final = transform.TransformFinalBlock(byte_encryptedData, 0, byte_encryptedData.Length);
 
      //生成结果
      string result = Encoding.UTF8.GetString(final);
 
      //反序列化结果,生成用户信息实例
      userInfo = JsonConvert.DeserializeObject<WechatUserInfo>(result);
 
      return userInfo;
 
    }
 
    /// <summary>
    /// 根据微信小程序平台提供的解密算法解密数据,推荐直接使用此方法
    /// </summary>
    /// <param name="loginInfo">登陆信息</param>
    /// <returns>用户信息</returns>
    public WechatUserInfo Decrypt(WechatLoginInfo loginInfo)
    {
      if (loginInfo == null)
        return null;
 
      if (String.IsNullOrEmpty(loginInfo.code))
        return null;
 
      OpenIdAndSessionKey oiask = DecodeOpenIdAndSessionKey(loginInfo);
 
      if (oiask == null)
        return null;
 
      if (!VaildateUserInfo(loginInfo, oiask))
        return null;
 
      WechatUserInfo userInfo = Decrypt(loginInfo.encryptedData, loginInfo.iv, oiask.session_key);
 
      return userInfo;
    }
 
    /// <summary>
    /// GET请求
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    private string GetResponse(string url)
    {
      if (url.StartsWith("https"))
        System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
 
      HttpClient httpClient = new HttpClient();
      httpClient.DefaultRequestHeaders.Accept.Add(
      new MediaTypeWithQualityHeaderValue("application/json"));
      HttpResponseMessage response = httpClient.GetAsync(url).Result;
 
      if (response.IsSuccessStatusCode)
      {
        string result = response.Content.ReadAsStringAsync().Result;
        return result;
      }
      return null;
    }
 
    
  }
  /// <summary>
  /// 微信小程序登录信息结构
  /// </summary>
  public class WechatLoginInfo
  {
    public string code { get; set; }
    public string encryptedData { get; set; }
    public string iv { get; set; }
    public string rawData { get; set; }
    public string signature { get; set; }
  }
  /// <summary>
  /// 微信小程序用户信息结构
  /// </summary>
  public class WechatUserInfo
  {
    public string openId { get; set; }
    public string nickName { get; set; }
    public string gender { get; set; }
    public string city { get; set; }
    public string province { get; set; }
    public string country { get; set; }
    public string avatarUrl { get; set; }
    public string unionId { get; set; }
    public Watermark watermark { get; set; }
 
    public class Watermark
    {
      public string appid { get; set; }
      public string timestamp { get; set; }
    }
  }
  /// <summary>
  /// 微信小程序从服务端获取的OpenId和SessionKey信息结构
  /// </summary>
  public class OpenIdAndSessionKey
  {
    public string openid { get; set; }
    public string session_key { get; set; }
    public string errcode { get; set; }
    public string errmsg { get; set; }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:


  • 本文相关:
  • asp.net 数字签名实例代码
  • asp.net web.config中 数据库连接字符串加密解密
  • .net c#创建webservice服务简单实例
  • asp.net微信开发(已关注用户管理)
  • asp.net 权限管理分析
  • asp.net mvc 权限过滤和单点登录(禁止重复登录)
  • 如何在asp.net core类库项目中读取配置文件详解
  • asp.net core 2.0 使用支付宝pc网站支付实现代码
  • 实现asp.net多文件上传程序代码
  • asp.net程序优化js、css实现合并与压缩的方法
  • .net下为百度文本编辑器ueditor增加图片删除功能示例
  • asp.net 导出到csv文件乱码的问题
  • 免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved