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


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 相关文章推荐
JavaScript中“+=”的应用
Feb 02 Javascript
jscript之Read an Excel Spreadsheet
Jun 13 Javascript
用js实现判断当前网址的来路如果不是指定的来路就跳转到指定页面
May 02 Javascript
JavaScript实现简单的时钟实例代码
Nov 23 Javascript
jQuery选择器源码解读(四):tokenize方法的Expr.preFilter
Mar 31 Javascript
javascript基本包装类型介绍
Apr 10 Javascript
浅析jQuery Ajax请求参数和返回数据的处理
Feb 24 Javascript
详谈jQuery中的一些正则匹配表达式
Mar 08 Javascript
详解angularjs跨页面传参遇到的一些问题
Nov 01 Javascript
解决vue+ element ui 表单验证有值但验证失败问题
Jan 16 Javascript
Vue强制组件重新渲染的方法讨论
Feb 03 Javascript
详解JavaScript之ES5的继承
Jul 08 Javascript
一文了解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
第七节--类的静态成员
2006/11/16 PHP
mysql_fetch_assoc和mysql_fetch_row的功能加起来就是mysql_fetch_array
2007/01/15 PHP
Memcache 在PHP中的使用技巧
2010/02/08 PHP
PHP中register_globals参数为OFF和ON的区别(register_globals 使用详解)
2012/02/05 PHP
PHP闭包函数传参及使用外部变量的方法
2016/03/15 PHP
Thinkphp连表查询及数据导出方法示例
2016/10/15 PHP
PHP XML和数组互相转换详解
2016/10/26 PHP
php-fpm服务启动脚本的方法
2018/04/27 PHP
PHP实现数组转JSon和JSon转数组的方法示例
2018/06/14 PHP
Laravel 框架基于自带的用户系统实现登录注册及错误处理功能分析
2020/04/14 PHP
jQuery开发者都需要知道的5个小技巧
2010/01/08 Javascript
JQuery.ajax传递中文参数的解决方法 推荐
2011/03/28 Javascript
js中如何复制一个对象并获取其所有属性和属性对应的值
2013/10/24 Javascript
window.location.hash知识汇总
2015/11/09 Javascript
jQuery实现table中的tr上下移动并保持序号不变的实例代码
2016/07/11 Javascript
jquery实现ajax提交表单信息的简单方法(推荐)
2016/08/24 Javascript
详解VUE Element-UI多级菜单动态渲染的组件
2019/04/25 Javascript
JavaScript实现的弹出遮罩层特效经典示例【基于jQuery】
2019/07/10 jQuery
JS中==、===你分清楚了吗
2020/03/04 Javascript
JQuery通过键盘控制键盘按下与松开触发事件
2020/08/07 jQuery
Python入门学习之字符串与比较运算符
2015/10/12 Python
在Python中移动目录结构的方法
2016/01/31 Python
python-django中的APPEND_SLASH实现方法
2019/06/21 Python
Python和Anaconda和Pycharm安装教程图文详解
2020/02/04 Python
基于Tensorflow一维卷积用法详解
2020/05/22 Python
Django实现内容缓存实例方法
2020/06/30 Python
CSS3模拟IOS滑动开关效果
2016/09/28 HTML / CSS
canvas绘制表情包的示例代码
2018/07/09 HTML / CSS
技校毕业生自荐书
2014/05/23 职场文书
房屋所有权证明
2014/10/20 职场文书
世界遗产导游词
2015/02/13 职场文书
研究生论文答辩开场白
2015/05/27 职场文书
联谊会开场白
2015/06/01 职场文书
小学生禁毒教育心得体会
2016/01/15 职场文书
pandas进行数据输入和输出的方法详解
2022/03/23 Python
Nginx HTTP跳转至HTTPS
2022/05/15 Servers