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


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 相关文章推荐
js/jQuery对象互转(快速操作dom元素)
Feb 04 Javascript
jquery改变disabled的boolean状态的三种方法
Dec 13 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
Jan 08 Javascript
jQuery控制TR显示隐藏的几种方法
Jun 18 Javascript
JavaScript中的普通函数与构造函数比较
Apr 07 Javascript
jQuery处理XML文件的几种方法
Jun 14 Javascript
javascript 面向对象function详解及实例代码
Feb 28 Javascript
微信小程序教程系列之设置标题栏和导航栏(7)
Jun 29 Javascript
JavaScript创建对象方法实例小结
Sep 03 Javascript
详解一个基于套接字实现长连接的express
Mar 28 Javascript
基于JS实现简单滑块拼图游戏
Oct 12 Javascript
详解JavaScript的this指向和绑定
Sep 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
ASP和PHP都是可以删除自身的
2007/04/09 PHP
PHP关联链接常用代码
2012/11/05 PHP
深入理解:单一入口、MVC、ORM、CURD、ActiveRecord概念
2013/06/06 PHP
PHP下载远程文件到本地存储的方法
2015/03/24 PHP
php实现学生管理系统
2020/03/21 PHP
PHP 传输会话curl函数的实例详解
2017/09/12 PHP
laravel框架学习笔记之组件化开发实现方法
2020/02/01 PHP
javascript采用数组实现tab菜单切换效果
2012/12/12 Javascript
javascript实例分享---具有立体效果的图片特效
2014/06/08 Javascript
基于NodeJS的前后端分离的思考与实践(三)轻量级的接口配置建模框架
2014/09/26 NodeJs
jquery+javascript编写国籍控件
2015/02/12 Javascript
在Node.js应用中读写Redis数据库的简单方法
2015/06/30 Javascript
基于javascript实现彩票随机数生成(简单版)
2020/04/17 Javascript
微信小程序实现日历签到
2020/09/21 Javascript
微信小程序实现点赞业务
2021/02/10 Javascript
jquery实现广告上下滚动效果
2021/03/04 jQuery
Django的信号机制详解
2017/05/05 Python
Python实现动态图解析、合成与倒放
2018/01/18 Python
python实现ID3决策树算法
2018/08/29 Python
解决python ogr shp字段写入中文乱码的问题
2018/12/31 Python
CentOS6.9 Python环境配置(python2.7、pip、virtualenv)
2019/05/06 Python
Pyqt5 关于流式布局和滚动条的综合使用示例代码
2020/03/24 Python
使用Keras训练好的.h5模型来测试一个实例
2020/07/06 Python
利用HTML5绘制点线面组成的3D图形的示例
2015/05/12 HTML / CSS
STAUD官方网站:洛杉矶独有的闲适风格
2019/04/11 全球购物
巴西补充剂和维生素购物网站:Natue
2019/06/17 全球购物
迪奥美国官网:Dior美国
2019/12/07 全球购物
英国独特家具和家庭用品购物网站:Cuckooland
2020/08/30 全球购物
网络书店创业计划书
2014/02/07 职场文书
顶撞老师检讨书
2014/02/07 职场文书
机械制造专业毕业生求职信
2014/03/02 职场文书
2014年反洗钱工作总结
2014/11/22 职场文书
超外差式晶体管收音机的组装与统调
2021/04/22 无线电
为Java项目添加Redis缓存的方法
2021/05/18 Redis
使用Springboot实现健身房管理系统
2021/07/01 Java/Android
Python中with上下文管理协议的作用及用法
2022/03/18 Python