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


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 相关文章推荐
10个新的最有前途的JavaScript框架
Mar 12 Javascript
关于JavaScript的一些看法
May 27 Javascript
JavaScript弹出新窗口并控制窗口移动到指定位置的方法
Apr 06 Javascript
jQuery中layer分页器的使用
Mar 13 Javascript
vue webuploader 文件上传组件开发
Sep 23 Javascript
JavaScript 正则命名分组【推荐】
Jun 07 Javascript
解决Layui选择全部,换页checkbox复选框重新勾选的问题方法
Aug 14 Javascript
详解Vue Elementui中的Tag与页面其它元素相互交互的两三事
Sep 25 Javascript
JavaScript常用事件介绍
Jan 21 Javascript
Vue快速实现通用表单验证功能
Dec 05 Javascript
vue cli3.0打包上线静态资源找不到路径的解决操作
Aug 03 Javascript
解决vue打包 npm run build-test突然不动了的问题
Nov 13 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
PHP array_push 数组函数
2009/12/26 PHP
php引用地址改变变量值的问题
2012/03/23 PHP
PHP实现将科学计数法转换为原始数字字符串的方法
2014/12/16 PHP
Zend Framework教程之前端控制器Zend_Controller_Front用法详解
2016/03/07 PHP
php使用escapeshellarg时中文被过滤的解决方法
2016/07/10 PHP
php的socket编程详解
2016/11/20 PHP
PHP的JSON封装、转变及输出操作示例
2019/09/27 PHP
javascript jQuery $.post $.ajax用法
2008/07/09 Javascript
js自定义事件代码说明
2011/01/31 Javascript
基于jquery自定义图片热区效果
2012/07/21 Javascript
jQuery中$.click()无效问题分析
2015/01/29 Javascript
Angular.JS学习之依赖注入$injector详析
2016/10/20 Javascript
Vue数据驱动模拟实现2
2017/01/11 Javascript
微信小程序 地图map实例详解
2017/06/07 Javascript
浅谈微信小程序之官方UI框架we-ui使用教程
2018/08/20 Javascript
element-ui表格数据转换的示例代码
2018/08/24 Javascript
webpack打包nodejs项目的方法
2018/09/26 NodeJs
微信小程序进入广告实现代码实例
2019/09/19 Javascript
Vue-cli项目部署到Nginx服务器的方法
2019/11/01 Javascript
python的常见命令注入威胁
2013/02/18 Python
Python map和reduce函数用法示例
2015/02/26 Python
pytorch ImageFolder的覆写实例
2020/02/20 Python
CSS3 transform的skew属性值图文详解
2014/07/21 HTML / CSS
CSS中的字体大小设置属性总结
2016/05/24 HTML / CSS
使用CSS3的box-sizing属性解决div宽高被内边距撑开的问题
2016/06/28 HTML / CSS
台湾线上百货零售购物平台:friDay购物
2017/08/18 全球购物
英国领先的维生素和营养补充剂直接供应商:Healthspan
2019/04/22 全球购物
C#里面可以避免一个类被其他类继承么?如何?
2013/09/26 面试题
职工趣味运动会方案
2014/02/10 职场文书
市级绿色学校申报材料
2014/08/25 职场文书
2014年9.18纪念日演讲稿
2014/09/14 职场文书
内勤岗位职责范本
2015/04/13 职场文书
小学数学教师研修感悟
2015/11/18 职场文书
react中props 的使用及进行限制的方法
2021/04/28 Javascript
使用springMVC所需要的pom配置
2021/09/15 Java/Android
Windows Server 2008 修改远程登录端口以及配置防火墙
2022/04/28 Servers