微信小程序 用户数据解密详细介绍


Posted in Javascript onJanuary 09, 2017

微信小程序 用户数据解密

官方指引图:

微信小程序 用户数据解密详细介绍

引导图一步一步操作

1、获取code

onLoad: function (options) {
  // 页面初始化 options为页面跳转所带来的参数
  let that = this
  wx.login({
   success: function (res) {
    // success
    let code = res.code
    that.setData({ code: code })
    wx.getUserInfo({
     success: function (res) {
      // success
      that.setData({ userInfo: res.userInfo })
      that.setData({ iv: res.iv })
      that.setData({ encryptedData: res.encryptedData })
      that.get3rdSession()
     }
    })
   }
 })
}

2、发送code到第三方服务器,获取3rd_session

get3rdSession:function(){
  let that = this
  wx.request({
   url: 'https://localhost:8443/get3rdSession',
   data: {
    code: this.data.code
   },
   method: 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
   // header: {}, // 设置请求的 header
   success: function (res) {
    // success
    var sessionId = res.data.session;
    that.setData({ sessionId: sessionId })
    wx.setStorageSync('sessionId', sessionId)
    that.decodeUserInfo()
   }
  })
 }

3、在第三方服务器上发送appid、appsecret、code到微信服务器换取session_key和openid

这里使用JFinal搭建的服务器

Redis配置

public void configPlugin(Plugins me) {
  //用于缓存userinfo模块的redis服务
  RedisPlugin userInfoRedis = new RedisPlugin("userInfo","localhost");
  me.add(userInfoRedis);
}

获取第三方session

public void get3rdSession() {
  //获取名为userInfo的Redis Cache对象
  Cache userInfoCache = Redis.use("userInfo");
  String sessionId = "";
  JSONObject json = new JSONObject();
  String code = getPara("code");
  String url = "https://api.weixin.qq.com/sns/jscode2session?appid=wx7560b8008e2c445d&secret=f1af3312b7038513fd17dd9cbc3b357c&js_code=" + code + "&grant_type=authorization_code";
  //执行命令生成3rd_session
  String session = ExecLinuxCMDUtil.instance.exec("cat /dev/urandom |od -x | tr -d ' '| head -n 1").toString();
  json.put("session", session);
  //创建默认的httpClient实例
  CloseableHttpClient httpClient = getHttpClient();
  try {
    //用get方法发送http请求
    HttpGet get = new HttpGet(url);
    System.out.println("执行get请求:...." + get.getURI());
    CloseableHttpResponse httpResponse = null;
    //发送get请求
    httpResponse = httpClient.execute(get);
    try {
      //response实体
      HttpEntity entity = httpResponse.getEntity();
      if (null != entity) {
        String result = EntityUtils.toString(entity);
        System.out.println(result);
        JSONObject resultJson = JSONObject.fromObject(result);
        String session_key = resultJson.getString("session_key");
        String openid = resultJson.getString("openid");
        //session存储
        userInfoCache.set(session,session_key+","+openid);
        }
      } finally {
        httpResponse.close();
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        closeHttpClient(httpClient);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    renderJson(json);
}
private CloseableHttpClient getHttpClient() {
  return HttpClients.createDefault();
}

private void closeHttpClient(CloseableHttpClient client) throws IOException {
  if (client != null) {
    client.close();
  }
}

ExecLinuxCMDUtil.Java

import java.io.InputStreamReader;
import java.io.LineNumberReader;

/**
 * java在linux环境下执行linux命令,然后返回命令返回值。
 * Created by LJaer on 16/12/22.
 */
public class ExecLinuxCMDUtil {
  public static final ExecLinuxCMDUtil instance = new ExecLinuxCMDUtil();

  public static Object exec(String cmd) {
    try {
      String[] cmdA = { "/bin/sh", "-c", cmd };
      Process process = Runtime.getRuntime().exec(cmdA);
      LineNumberReader br = new LineNumberReader(new InputStreamReader(
          process.getInputStream()));
      StringBuffer sb = new StringBuffer();
      String line;
      while ((line = br.readLine()) != null) {
        System.out.println(line);
        sb.append(line).append("\n");
      }
      return sb.toString();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
}

4、解密用户数据

decodeUserInfo:function(){
  let that = this
  wx.request({
   url: 'https://localhost:8443/decodeUserInfo',
   data: {
    encryptedData: that.data.encryptedData,
    iv: that.data.iv,
    session: wx.getStorageSync('sessionId')
   },
   method: 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
   // header: {}, // 设置请求的 header
   success: function (res) {
    // success
    console.log(res)
   }
  })
}

console输出结果:

微信小程序 用户数据解密详细介绍

后端解密代码

/**
 * 解密用户敏感数据
 */
public void decodeUserInfo(){
  String encryptedData = getPara("encryptedData");
  String iv = getPara("iv");
  String session = getPara("session");
  //从缓存中获取session_key
  //获取名称为userInfo的Redis Cache对象
  Cache userInfoRedis = Redis.use("userInfo");
  Object wxSessionObj = userInfoRedis.get(session);
  if(null==wxSessionObj){
    renderNull();
  }
  String wxSessionStr = (String)wxSessionObj;
  String session_key = wxSessionStr.split(",")[0];


  try {
    byte[] resultByte = AESUtil.instance.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(session_key), Base64.decodeBase64(iv));
    if(null != resultByte && resultByte.length > 0){
      String userInfo = new String(resultByte, "UTF-8");
      System.out.println(userInfo);
      JSONObject json = JSONObject.fromObject(userInfo); //将字符串{“id”:1}
      renderJson(json);
    }
  } catch (InvalidAlgorithmParameterException e) {
    e.printStackTrace();
  } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
  }
}

AESUtil.java

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;

public class AESUtil {
  public static final AESUtil instance = new AESUtil();

  public static boolean initialized = false;

  /**
   * AES解密
   * @param content 密文
   * @return
   * @throws InvalidAlgorithmParameterException
   * @throws NoSuchProviderException
   */
  public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
    initialize();
    try {
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
      Key sKeySpec = new SecretKeySpec(keyByte, "AES");

      cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
      byte[] result = cipher.doFinal(content);
      return result;
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
    } catch (InvalidKeyException e) {
      e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
      e.printStackTrace();
    } catch (BadPaddingException e) {
      e.printStackTrace();
    } catch (NoSuchProviderException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return null;
  }

  public static void initialize(){
    if (initialized) return;
    Security.addProvider(new BouncyCastleProvider());
    initialized = true;
  }
  //生成iv
  public static AlgorithmParameters generateIV(byte[] iv) throws Exception{
    AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
    params.init(new IvParameterSpec(iv));
    return params;
  }
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
修改好的jquery滚动字幕效果实现代码
Jun 22 Javascript
你必须知道的JavaScript 变量命名规则详解
May 07 Javascript
解决js中window.open弹出的是上次的缓存页面问题
Dec 29 Javascript
jquery图片播放浏览插件prettyPhoto使用详解
Dec 19 Javascript
jQuery增加自定义函数的方法
Jul 18 Javascript
实例讲解jquery中mouseleave和mouseout的区别
Feb 17 Javascript
JS实现列表的响应式排版(推荐)
Sep 01 Javascript
JS键盘版计算器的制作方法
Dec 03 Javascript
Vue插值、表达式、分隔符、指令知识小结
Oct 12 Javascript
使用VueRouter的addRoutes方法实现动态添加用户的权限路由
Jun 03 Javascript
Ant Design的Table组件去除
Oct 24 Javascript
ant design中upload组件上传大文件,显示进度条进度的实例
Oct 29 Javascript
微信小程序 摇一摇抽奖简单实例实现代码
Jan 09 #Javascript
jQuery实现弹出窗口弹出div层的实例代码
Jan 09 #Javascript
Bootstrap实现渐变顶部固定自适应导航栏
Aug 27 #Javascript
微信小程序 实战程序简易新闻的制作
Jan 09 #Javascript
jquery实现多次上传同一张图片
Jan 09 #Javascript
微信小程序 欢迎页面的制作(源码下载)
Jan 09 #Javascript
微信小程序 开发之快递查询功能的实现
Jan 09 #Javascript
You might like
Yii的Srbac插件用法详解
2016/07/14 PHP
jQuery 对象中的类数组操作
2009/04/27 Javascript
JavaScript 匿名函数(anonymous function)与闭包(closure)
2011/10/04 Javascript
js冒泡法和数组转换成字符串示例代码
2013/08/14 Javascript
jQuery函数map()和each()介绍及异同点分析
2014/11/08 Javascript
JQuery实现超链接鼠标提示效果的方法
2015/06/10 Javascript
BootStrap智能表单实战系列(三)分块表单配置详解
2016/06/13 Javascript
解析Javascript单例模式概念与实例
2016/12/05 Javascript
关于vuex的学习实践笔记
2017/04/05 Javascript
vue-router单页面路由
2017/06/17 Javascript
超级简易的JS计算器实例讲解(实现加减乘除)
2017/08/08 Javascript
JS获取一个表单字段中多条数据并转化为json格式
2017/10/17 Javascript
nodeJs实现基于连接池连接mysql的方法示例
2018/02/10 NodeJs
angularjs手动识别字符串中的换行符方法
2018/10/02 Javascript
Vue实现移动端左右滑动效果的方法
2018/11/27 Javascript
vuex刷新后数据丢失的解决方法
2020/10/18 Javascript
js回到页面指定位置的三种方式
2020/12/17 Javascript
JS+CSS实现过渡特效
2021/01/02 Javascript
使用Python求解最大公约数的实现方法
2015/08/20 Python
Python Sql数据库增删改查操作简单封装
2016/04/18 Python
python3 对list中每个元素进行处理的方法
2018/06/29 Python
python pandas库的安装和创建
2019/01/10 Python
在django中form的label和verbose name的区别说明
2020/05/20 Python
PyCharm中配置PySide2的图文教程
2020/06/18 Python
Python分类测试代码实例汇总
2020/07/23 Python
Scrapy+Selenium自动获取cookie爬取网易云音乐个人喜爱歌单
2021/02/01 Python
新秀丽拉杆箱美国官方网站:Samsonite美国
2016/07/25 全球购物
Linux操作面试题
2012/05/16 面试题
口腔医学技术应届生求职信
2013/11/09 职场文书
最受欢迎的自我评价
2013/12/22 职场文书
社保转移委托书范本
2014/10/08 职场文书
小学见习报告
2015/06/23 职场文书
如何写好活动总结
2019/06/21 职场文书
Python办公自动化之教你用Python批量识别发票并录入到Excel表格中
2021/06/26 Python
Python+Appium自动化测试的实战
2021/06/30 Python
5种方法告诉你如何使JavaScript 代码库更干净
2021/09/15 Javascript