微信小程序登录数据解密及状态维持实例详解


Posted in Javascript onMay 06, 2019

本文实例讲述了微信小程序登录数据解密及状态维持。分享给大家供大家参考,具体如下:

学习过小程序的朋友应该知道,在小程序中是不支持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)

运行输出

微信小程序登录数据解密及状态维持实例详解

希望本文所述对大家微信小程序开发有所帮助。

Javascript 相关文章推荐
jquery 模式对话框终极版实现代码
Sep 28 Javascript
关于IE BUG与字符串截取substr的解决办法
Apr 10 Javascript
Jquery attr(&quot;checked&quot;) 返回checked或undefined 获取选中失效
Oct 10 Javascript
js/jQuery简单实现选项卡功能
Jan 02 Javascript
Javascript中的String对象详谈
Mar 03 Javascript
javascript中类的定义方式详解(四种方式)
Dec 22 Javascript
JS使用正则实现去掉字符串左右空格的方法
Dec 27 Javascript
vue实现留言板todolist功能
Aug 16 Javascript
VueJS组件之间通过props交互及验证的方式
Sep 04 Javascript
详解a标签添加onclick事件的几种方式
Mar 29 Javascript
微信小程序new Date()方法失效问题解决方法
Jul 29 Javascript
jQuery实现广告显示和隐藏动画
Jul 04 jQuery
一文了解Vue中的nextTick
May 06 #Javascript
angular 服务随记小结
May 06 #Javascript
详解如何使用nvm管理Node.js多版本
May 06 #Javascript
关于AOP在JS中的实现与应用详解
May 06 #Javascript
JS使用iView的Dropdown实现一个右键菜单
May 06 #Javascript
一文读懂ES7中的javascript修饰器
May 06 #Javascript
JavaScript中AOP的实现与应用
May 06 #Javascript
You might like
PHP中设置时区方法小结
2012/06/03 PHP
PHP漏洞全解(详细介绍)
2012/11/13 PHP
PHP框架自动加载类文件原理详解
2017/06/06 PHP
jquery遍历checkbox介绍
2014/02/21 Javascript
获取当前点击按钮的id用this.id实现
2014/03/17 Javascript
JS数组去掉重复数据只保留一条的实现代码
2016/08/11 Javascript
基于JQuery实现的跑马灯效果(文字无缝向上翻动)
2016/12/02 Javascript
Vue.js学习之过滤器详解
2017/01/22 Javascript
谈谈对vue响应式数据更新的误解
2017/08/01 Javascript
Vue 过滤器filters及基本用法
2017/12/26 Javascript
使用webpack构建应用的方法步骤
2019/03/04 Javascript
Node.js在图片模板上生成二维码图片并附带底部文字说明实现详解
2019/08/07 Javascript
用原生JS实现爱奇艺首页导航栏代码实例
2019/09/19 Javascript
vue双向绑定数据限制长度的方法
2019/11/04 Javascript
vue实现用户长时间不操作自动退出登录功能的实现代码
2020/07/23 Javascript
Vue自定义组件双向绑定实现原理及方法详解
2020/09/03 Javascript
Django+Xadmin构建项目的方法步骤
2019/03/06 Python
对python 中re.sub,replace(),strip()的区别详解
2019/07/22 Python
Python 中判断列表是否为空的方法
2019/11/24 Python
python中的数组赋值与拷贝的区别详解
2019/11/26 Python
Python3 实现减少可调用对象的参数个数
2019/12/20 Python
Python高阶函数、常用内置函数用法实例分析
2019/12/26 Python
Python logging模块原理解析及应用
2020/08/13 Python
html5视频播放_动力节点Java学院整理
2017/07/13 HTML / CSS
澳大利亚购买太阳镜和眼镜网站:Glamoureyes
2020/09/22 全球购物
全球精选男装和家居用品:Article
2020/04/13 全球购物
计算机专业个人求职自荐信
2013/09/21 职场文书
校园十佳歌手策划书
2014/01/22 职场文书
开展党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
2015年党风廉政承诺书
2015/01/22 职场文书
护理专业自我评价
2015/03/11 职场文书
检讨书格式范文
2015/05/07 职场文书
学校后勤工作总结2015
2015/05/15 职场文书
矛盾论读书笔记
2015/06/29 职场文书
GoLang中生成UUID唯一标识的实现
2021/05/08 Golang
德劲DE1102数字调谐收音机机评
2022/04/07 无线电