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


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 相关文章推荐
Firefox 无法获取cssRules 的解决办法
Oct 11 Javascript
javascript读取RSS数据
Jan 20 Javascript
javascript for循环从入门到偏门(效率优化+奇特用法)
Aug 01 Javascript
Javascript模仿淘宝信用评价实例(附源码)
Nov 26 Javascript
谈谈我对JavaScript原型和闭包系列理解(随手笔记8)
Dec 24 Javascript
基于jquery实现最简单的选项卡切换效果
May 08 Javascript
关于js二维数组和多维数组的定义声明(详解)
Oct 02 Javascript
AngularJS定时器的使用与移除操作方法【interval与timeout】
Dec 14 Javascript
前端必备插件之纯原生JS的瀑布流插件Macy.js
Nov 22 Javascript
微信小程序时间标签和时间范围的联动效果
Feb 15 Javascript
JavaScript实现简单的弹窗效果
May 19 Javascript
解决vue页面渲染但dom没渲染的操作
Jul 27 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
Session的工作方式
2006/10/09 PHP
PHP中include()与require()的区别说明
2010/03/10 PHP
PHP无限分类(树形类)
2013/09/28 PHP
Yii 2.0自带的验证码使用经验分享
2017/06/19 PHP
php处理抢购类功能的高并发请求
2018/02/08 PHP
php文件包含的几种方式总结
2019/09/19 PHP
理清apply(),call()的区别和关系
2011/08/14 Javascript
使用jquery写个更改表格行顺序的小功能
2014/04/29 Javascript
FF(火狐)浏览器无法执行window.close()解决方案
2014/11/13 Javascript
javascript批量修改文件编码格式的方法
2015/01/27 Javascript
深入讲解AngularJS中的自定义指令的使用
2015/06/18 Javascript
JavaScript实现网页加载进度条代码超简单
2015/09/21 Javascript
每天一篇javascript学习小结(属性定义方法)
2015/11/19 Javascript
JavaScript提高性能知识点汇总
2016/01/15 Javascript
javascript中JSON.parse()与eval()解析json的区别
2016/05/19 Javascript
AngularJS ng-mousedown 指令
2016/08/02 Javascript
深入理解jQuery layui分页控件的使用
2016/08/17 Javascript
vue移动端下拉刷新和上拉加载的实现代码
2018/09/08 Javascript
详解Vue项目在其他电脑npm run dev运行报错的解决方法
2018/10/29 Javascript
浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验
2018/12/20 Javascript
微信小程序实现左右列表联动
2020/05/19 Javascript
[44:47]Ti4 循环赛第三日 iG vs NaVi
2014/07/12 DOTA
[01:34]传奇从这开始 2016国际邀请赛中国区预选赛震撼开启
2016/06/26 DOTA
python实现键盘控制鼠标移动
2020/11/27 Python
python实现的Iou与Giou代码
2020/01/18 Python
PyTorch中的C++扩展实现
2020/04/02 Python
python连接mongodb数据库操作数据示例
2020/11/30 Python
CSS 3.0文字悬停跳动特效代码
2020/10/26 HTML / CSS
GAP欧盟网上商店:GAP EU
2016/09/13 全球购物
澳大利亚先进的皮肤和激光诊所购物网站:Soho Skincare
2018/10/15 全球购物
澳大利亚家具和家居用品购物网站:Zanui
2018/12/29 全球购物
岗位职责风险点
2014/03/12 职场文书
大学生社团活动总结
2014/04/26 职场文书
开场白怎么写
2015/06/01 职场文书
2015上半年个人工作总结
2015/07/27 职场文书
Go语言基础函数基本用法及示例详解
2021/11/17 Golang