微信小程序登錄數據解密以及狀態維持


學習過小程序的朋友應該知道,在小程序中是不支持cookie的,借助小程序中的緩存我們也可以存儲一些信息,但是對於一些比較重要的信息,我們需要通過登錄狀態維持來保存,同時,為了安全起見,用戶的敏感信息,也是需要加密在網絡上傳輸的。

前台,service。封裝了http請求,同時封裝了getSession(通過code獲取服務器生成的session)、getUserInfo(獲取用戶信息)、getDecryptionData(解密數據)

//service.js
//封裝了http服務,getUserInfo,提供回調函數
var recourse = {
  doMain: "http://www.domain.com/"
}
module.exports = {
  //Http Get
  requestGet: function (url, data, cb) {
    wx.request({
      url: recourse.doMain + url,
      data: data,
      method: 'GET',
      header: {},
      success: function (res) {
        cb(res, true)
      },
      fail: function () {
        cb(data, false)
      }
    })
  },
  //Http POST
  requestPost: function (url, data, cb) {
    wx.request({
      url: recourse.doMain + url,
      data: data,
      method: 'POST',
      header: {},
      success: function (res) {
        cb(res, true)
      },
      fail: function () {
        cb(data, false)
      }
    })
  },
  //獲取第三方sessionId
  getSession: function (code, cb) {
    wx.request({
      url: recourse.doMain + 'SmallRoutine/PostCode',
      data: { code: code },
      method: 'POST',
      success: function (res) {
        cb(res, true)
      },
      fail: function (res) {
        cb(res, false)
      }
    })
  },
  //獲取用戶信息
  getUserInfo: function (cb) {
    wx.getUserInfo({
      success: function (res) {
        cb(res, true)
      },
      fail: function (res) {
        cb(res, false)
      }
    })
  },
  //獲取解密數據
  getDecryptionData: function (cb) {
    wx.request({
      url: recourse.doMain+'SmallRoutine/Decryption',
      data: {
        encryptedData: wx.getStorageSync('encryptedData'),
        iv:  wx.getStorageSync('iv'),
        session:  wx.getStorageSync('thirdSessionId'),
      },
      method: 'POST',
      success: function (res) {
        cb(res, true)
      },
      fail: function (res) {
        cb(res, false)
      }
    })
  }
}

 后台,根據code獲取session,客戶端用來保持登錄狀態

[HttpPost]
public ActionResult PostCode(string code)
{
    try
    {
        if(!string.IsNullOrEmpty(code))
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code",appId,appSecret,code));
            request.Method = "GET";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader sr = new StreamReader(response.GetResponseStream());
            string content = sr.ReadToEnd();
            if(response.StatusCode == HttpStatusCode.OK)
            {
                var successModel = Newtonsoft.Json.JsonConvert.DeserializeObject<ValidateCodeSuccess>(content);
                if(null != successModel.session_key)
                {
                    //session_key是微信服務器生成的針對用戶數據加密簽名的密鑰,不應該傳輸到客戶端
                    var session_key = successModel.session_key;
                    //3re_session用於服務器和小程序之間做登錄狀態校驗
                    var thirdSession = Guid.NewGuid().ToString().Replace("-","");
                    var now = DateTime.Now;
                    //存到數據庫或者redis緩存,這里一小時過期
                    Service.AddLogin(new Domain.Login()
                    {
                        Code = code,
                        Createime = now,
                        OpenId = successModel.openid,
                        OverdueTime = now.AddMinutes(60),
                        SessionKey = successModel.session_key,
                        SessionRd = thirdSession
                    });
                    return Json(new { success = true,session = thirdSession,openId = successModel.openid });
                }
                else
                {
                    var errModel = Newtonsoft.Json.JsonConvert.DeserializeObject<ValidateCodeFail>(content);
                    return Json(new { success = false,msg = errModel.errcode + ":" + errModel.errmsg });
                }
            }
            else
            {
                var errModel = Newtonsoft.Json.JsonConvert.DeserializeObject<ValidateCodeFail>(content);
                return Json(new { success = false,msg = errModel.errcode + ":" + errModel.errmsg });
            }
        }
        else
        {
            return Json(new { success = false,msg = "code不能為null" });
        }
    }
    catch(Exception e)
    {
        return Json(new { success = false });
    }
}

 解密敏感信息

[HttpPost]
public ActionResult Decryption(string encryptedData,string iv,string session)
{
    try
    {
        var sessionKey = Service.GetSessionKey(session);
        if(!string.IsNullOrEmpty(sessionKey))
        {
            var str = AESDecrypt(encryptedData,sessionKey,iv);
            var data = Newtonsoft.Json.JsonConvert.DeserializeObject<EncryptedData>(str);
            if(null != data)
            {
                //服務器可以更新用戶信息
                return Json(new { success = true,data = data });
            }
        }
    }
    catch(Exception e)
    {
        Service.AddLog("翻譯錯誤:"+e.ToString());
    }
    return Json(new { success = false });
}

AES解密

public static string AESDecrypt(string encryptedData,string key,string iv)
{
    if(string.IsNullOrEmpty(encryptedData)) return "";
    byte[] encryptedData2 = Convert.FromBase64String(encryptedData);
    System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
    {
        Key = Convert.FromBase64String(key),
        IV = Convert.FromBase64String(iv),
        Mode = System.Security.Cryptography.CipherMode.CBC,
        Padding = System.Security.Cryptography.PaddingMode.PKCS7
    };
    System.Security.Cryptography.ICryptoTransform ctf = rm.CreateDecryptor();
    Byte[] resultArray = ctf.TransformFinalBlock(encryptedData2,0,encryptedData2.Length);
    return Encoding.UTF8.GetString(resultArray);
}

判斷用戶是否掉線

[HttpPost]
public ActionResult PostSession(string session)
{
    if(!string.IsNullOrEmpty(session))
    {
        var loginInfo = Service.GetLoginInfo(session);
        if(null != loginInfo)
        {
            return Json(new { success = true,openId = loginInfo.OpenId });
        }
        else
        {
            return Json(new { success = false });
        }
    }
    return Json(new { success = false });
}

前台index.js

//index.js
var app = getApp()
Page({
  data: {
    userInfo: {},
  },
  onLoad: function () {
    var that = this
    app.getUserInfo(function (userInfo) {
      //更新數據
      that.setData({
        userInfo: userInfo
      })
    })
  }
})

前台app.js

var service = require('./service/service.js')
var appConfig = {
    getUserInfo: function (cb) {
        var that = this
        if (that.globalData.userInfo) {
            //從緩存中用戶信息
        } else {
            //wx api 登錄
            wx.login({
                success: function (res) {
                    console.log('登錄成功 code 為:' + res.code);
                    if (res.code) {
                        service.getSession(res.code, function (res, success) {
                            if (success) {
                                console.log('通過 code 獲取第三方服務器 session 成功, session 為:' + res.data.session);
                                //緩存起來
                                wx.setStorageSync('thirdSessionId', res.data.session);
                                //wx api 獲取用戶信息
                                service.getUserInfo(function (res, success) {
                                    if (success) {
                                        console.log('獲取用戶信息成功, 加密數據為:' + res.encryptedData);
                                        console.log('獲取用戶信息成功, 加密向量為:' + res.iv);
                                        //緩存敏感的用戶信息,解密向量
                                        wx.setStorageSync('encryptedData', res.encryptedData);
                                        wx.setStorageSync('iv', res.iv);
                                        that.globalData.userInfo = res.userInfo;
                                        //解密數據
                                        service.getDecryptionData(function (res, success) {
                                            if (success) {
                                                console.log("解密數據成功");                                                
                                                console.log(res.data.data);
                                            } else {
                                                console.log('解密數據失敗');
                                            }
                                        })
                                    } else {
                                        console.log('獲取用戶信息失敗')
                                    }
                                });
                            } else {
                                console.log('通過 code 獲取第三方服務器 session 失敗');
                            }
                        });
                    } else {
                        console.log('登錄失敗:');
                    }
                }
            })
        }
    },
    globalData: {
        userInfo: null
    }
}
App(appConfig) 

運行輸出


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM