.NET微信小程序用戶數據的簽名驗證和解密代碼

這篇文章主要介紹了.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; }
  }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持神馬文庫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章