准备知识:

  1. Base64编解码
  2. AES算法、填充模式、偏移向量
  3. session_key会话密钥,以及怎么存储和获取

以上3点对于理解解密流程非常重要。

根据官方文档,我梳理了大致的解密流程,如下:

  1. 小程序客户端调用wx.login,回调里面包含js_code。
  2. 然后将js_code发送到服务器A(开发者服务器),服务器A向微信服务器发起请求附带js_code、appId、secretkey和grant_type参数,以换取用户的openid和session_key(会话密钥)。
  3. 服务器A拿到session_key后,生成一个随机数我们叫3rd_session,以3rdSessionId为key,以session_key + openid为value缓存到redis或memcached中;因为微信团队不建议直接将session_key在网络上传输,由开发者自行生成唯一键与session_key关联。其作用是:
    1. 将3rdSessionId返回给客户端,维护小程序登录态。
    2. 通过3rdSessionId找到用户session_key和openid。
  4. 客户端拿到3rdSessionId后缓存到storage,
  5. 通过wx.getUserIinfo可以获取到用户敏感数据encryptedData 。
  6. 客户端将encryptedData、3rdSessionId和偏移量一起发送到服务器A
  7. 服务器A根据3rdSessionId从缓存中获取session_key
  8. 在服务器A使用AES解密encryptedData,从而实现用户敏感数据解密

重点在6、7、8三个环节。
AES解密三个参数:

  • 密文 encryptedData
  • 密钥 aesKey
  • 偏移向量 iv

服务端解密流程:

  1. 密文和偏移向量由客户端发送给服务端,对这两个参数在服务端进行Base64_decode解编码操作。
  2. 根据3rdSessionId从缓存中获取session_key,对session_key进行Base64_decode可以得到aesKey,aes密钥。
  3. 调用aes解密方法,算法为 AES-128-CBC,数据采用PKCS#7填充。

下面结合小程序实例说明解密流程:

  1. 微信登录,获取用户信息

    var that = this;
    wx.login({
    success: function (res) {
    //微信js_code
    that.setData({wxcode: res.code});
    //获取用户信息
    wx.getUserInfo({
    success: function (res) {
    //获取用户敏感数据密文和偏移向量
    that.setData({encryptedData: res.encryptedData})
    that.setData({iv: res.iv})
    }
    })
    }
    })
  2. 使用code换取3rdSessionId

    var httpclient = require('../../utils/httpclient.js')
    VAR that = this
    //httpclient.req(url, data, method, success, fail)
    httpclient.req(
    'http://localhost:8090/wxappservice/api/v1/wx/getSession',
    {
    apiName: 'WX_CODE',
    code: this.data.wxcode
    },
    'GET',
    function(result){
    var thirdSessionId = result.data.data.sessionId;
    that.setData({thirdSessionId: thirdSessionId})
    //将thirdSessionId放入小程序缓存
    wx.setStorageSync('thirdSessionId', thirdSessionId)
    },
    function(result){
    console.log(result)
    }
    );
  3. 发起解密请求

    //httpclient.req(url, data, method, success, fail)
    httpclient.req(
    'http://localhost:8090/wxappservice/api/v1/wx/decodeUserInfo',
    {
    apiName: 'WX_DECODE_USERINFO',
    encryptedData: this.data.encryptedData,
    iv: this.data.iv,
    sessionId: wx.getStorageSync('thirdSessionId')
    },
    'GET',
    function(result){
    //解密后的数据
    console.log(result.data)
    },
    function(result){
    console.log(result)
    }
    );
  4. 服务端解密实现(java)

    /**  * 解密用户敏感数据  * @param encryptedData 明文  * @param iv  加密算法的初始向量  * @param sessionId  会话ID  * @return  */
    @Api(name = ApiConstant.WX_DECODE_USERINFO)
    @RequestMapping(value = "/api/v1/wx/decodeUserInfo", method = RequestMethod.GET, produces = "application/json")
    public Map<String,Object> decodeUserInfo(@RequestParam(required = true,value = "encryptedData")String encryptedData, @RequestParam(required = true,value = "iv")String iv, @RequestParam(required = true,value = "sessionId")String sessionId){ //从缓存中获取session_key
    Object wxSessionObj = redisUtil.get(sessionId);
    if(null == wxSessionObj){
    return rtnParam(40008, null);
    }
    String wxSessionStr = (String)wxSessionObj;
    String sessionKey = wxSessionStr.split("#")[0]; try {
    AES aes = new AES();
    byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
    if(null != resultByte && resultByte.length > 0){
    String userInfo = new String(resultByte, "UTF-8");
    return rtnParam(0, userInfo);
    }
    } catch (InvalidAlgorithmParameterException e) {
    e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    }
    return rtnParam(50021, null);
    }
  5. AES解密核心代码

    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();
    }

小程序encryptedData的更多相关文章

  1. 微信小程序java8 java7 java6 encryptedData 解密 异常处理

    使用java8 java7  java6 解密微信小程序encryptedData可以回遇到一些错误 1.java.security.NoSuchAlgorithmException: Cannot ...

  2. 小程序解密 encryptedData 获取 unionID 等信息

    index.php <?php include_once "wxBizDataCrypt.php"; // $appid 由小程序微信官方后台获取 $appid = 'wx4 ...

  3. 小程序Openid 获取,服务器 encryptedData 解密 遇到的坑

    获取客户 openId 和 unionId 需要以下步骤(都为必须步骤) 1.从验证从客户端传上来code, 获取sessionKey (需要配合小程序appid ,secret 发送到微信服务器) ...

  4. 微信小程序获取用户信息,解密encryptedData 包括敏感数据在内的完整用户信息的加密数据

    package com.iups.wx.wxservice; import java.io.UnsupportedEncodingException; import java.security.Alg ...

  5. .NET 小程序 wx.getUserInfo(OBJECT) 解密 encryptedData 来获取UnionId

    在小程序中通过 wx.getUserInfo 获取用户信息,而UnionId 只有关主了公众号才会返回,不关注公众号想获取UnionId则需要我们从返回的 encryptedData 中解码从而获取U ...

  6. 小程序登录解密用户数据encryptedData -41001: encodingAesKey 非法

    问题: 做小程序微信授权登录,先获取code,然后去获取到session_key和open_id,再拿到encryptedData,传到服务器去解密拿到用户信息,但是有时成功,有时返回-41001错误 ...

  7. 微信小程序加密数据(encryptedData)解密中的PHP代码,php7.1报错

    问题描述 最近在开发微信小程序涉及到加密数据(encryptedData)的解密,用的是PHP代码,在运行后报错mcrypt_module_ xxx is deprecated,提示方法已过时了 经研 ...

  8. 微信小程序之用户数据解密(七)

    [未经作者本人同意,请勿以任何形式转载] 经常看到有点的小伙伴在群里问小程序用户数据解密流程,所以打算写一篇关于小程序用户敏感数据解密教程: 加密过程微信服务器完成,解密过程在小程序和自身服务器完成, ...

  9. 微信小程序-登陆、支付、模板消息

    wx.login(OBJECT) 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key).用户数据的加解密通讯需要 ...

随机推荐

  1. Jenkins的配置从节点中默认没有Launch agent via Java Web Start,该如何配置使用

    Jenkins的配置从节点中默认没有Launch agent via Java Web Start,如下图所示,而这种启动方式在Windows上是最方便的. 如何设置才能让出来呢? 1:打开" ...

  2. domain or business logic

    Here are a few of the questions you should ask when writing business logic: ¡Do you fully understand ...

  3. ios 百度地图使用

    第一步.引入 1.下载SDK  地址http://developer.baidu.com/map/index.php?title=iossdk/sdkiosdev-download 2.解压出Baid ...

  4. 【Beta Scrum】冲刺! 2/5

    1. 今日完成情况 人员 学号 分工 是否完成 完成情况 胡武成 031502610 学习java后端登录验证方式,尝试编写登录api N 刚学会springmvc登录token拦截,准备明天登录注册 ...

  5. [Jenkins] 如何修改jenkins上的环境变量

    现象 当本地的环境变量发生变化时,在jenkins 构建时里面访问的环境变量仍是之前旧的(未更新的)导致构建出现错误,比如我以我所遇到的问题进行简单写下,下面例子中我是涉及到修改 PYTHONPATH ...

  6. HDU2966 In case of failure(浅谈k-d tree)

    嘟嘟嘟 题意:给定\(n\)个二维平面上的点\((x_i, y_i)\),求离每一个点最近的点得距离的平方.(\(n \leqslant 1e5\)) 这就是k-d tree入门题了. k-d tre ...

  7. python opencv show图片,debug技巧

    debug的时候可以直接把图片画出来debug. imshow函数就是python opencv的展示图片的函数,第一个是你要起的图片名,第二个是图片本身.waitKey函数是用来展示图片多久的,默认 ...

  8. Linux中运行SpringBoot项目,永久运行

    将写好的springboot项目打成jar包: 项目右键 -- Run As -- Maven build... ---此时出现下图 1.Goals 中填写:install 2.Skip Tests复 ...

  9. 如何在Ubuntu18.04(Bionic Beaver)系统安装Teamviewer远程控制软件

    首先,打开TeamViewer的下载页面,下载Debian/Ubuntu的Deb安装包. 这里有64位和32位安装包选项.可以在Terminal(终端)中输入uname -a 查看自己系统版本是64位 ...

  10. centos7搭建elasticsearch

    Elasticsearch:负责日志检索和分析,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等 Logstash:对日志进行收集.过 ...