收藏
回答

请问如果session_key过期,getUserInfo按钮获得encryptData用什么加密?

在用户点击授权信息的按钮的之后,会获得授权拿到的用户的encryptData和iv

如果需要解密unionId,我需要拿着这两个数据和用户的sessionKey做解密

所以拿到encryptData的时候,会用wx.login去刷最新的sessionKey

但问题是,会不会刷到最新的sessionKey,但encryptData是用老的已经过期的sessionKey加密的?导致解密错误


那么用户点击getUserInfo解析unionId的最佳实践是什么呢?

页面先wx.login(),然后记录用户的sessionKey,然后用户点击页面上的getUserInfo的按钮,然后用存下来的sessionKey解密?

但这样会不会用户页面停留实践过久,然后点击按钮的时候导致sessionKey失效呢?

回答关注问题邀请回答
收藏

2 个回答

  • 赵有猫
    赵有猫
    2019-11-22

    先wx.login 然后再wx.getUserInfo,因为wx.login可能会更新sessionkey,如果需要用户主动授权的话,那就先用户点击授权,之后在执行wx.login+wx.getUserInfo 就行了,不要先getUserInfo再wx.login,sessionkey有可能已经刷新,后台就解不出来了

    2019-11-22
    赞同
    回复
  • 王浩
    王浩
    2019-10-18


    getUserInfo: function (e) {

       var encryptedData = e.detail.encryptedData;

       var iv = e.detail.iv;  

       //用户按了允许授权按钮后需要处理的逻辑方法体  

       if (e.detail.userInfo) {  

         this.setData({

           userInfo: e.detail.userInfo,

           hasUserInfo: true,

           avatarUrl: wx.getStorageSync('avatarUrl')

         })

         // 登录

         wx.login({

           success: res => {

             console.log(res)

             wx.request({

               url: wx.getStorageSync('serverurl') + "/advisorySmallUser/getuserInfo",

               data: {

                 code: res.code,

                 encryptedData: encryptedData,

                 iv: iv

               },

               method: "POST",

               header: {

                 'content-type': 'application/x-www-form-urlencoded' // 默认值

               },

               success: function (res) {    

               }

             });

           }

         })

       } else {

         console.log("用户按了拒绝按钮")

         //用户按了拒绝按钮

         wx.showModal({

           title: '警告',

           content: '您点击了拒绝授权,将无法进入小程序,请授权之后再进入!!!',

           showCancel: false,

           confirmText: '返回授权',

           success: function (res) {

             if (res.confirm) {

               wx.setStorageSync('hasUserInfo', false);

               console.log('用户点击了“返回授权”')

             }

           }

         })

       }

     },

    Java

    @RequestMapping(value = "/getuserInfo", method = RequestMethod.POST)
        @ResponseBody
        public JSONObject getUserInfo(String code, String encryptedData, String iv) {
            JSONObject jsondata = new JSONObject();
            if (StringUtils.isEmpty(code)) {
                jsondata.put(ConstantUtils.STATUS, ConstantUtils.ZERO);
                jsondata.put(ConstantUtils.MSG, "code不能为空");
                log.error("code不能为空");
                return jsondata;
            }
            String appid = "appid";
            String appsecret = "appsecret";
            jsondata = MgWeChat.getOpenId(appid, appsecret, code);
            if (jsondata.get("openid") != null) {
                System.out.println(jsondata.get("openid"));
                System.out.println(jsondata.get("session_key"));
                System.out.println(jsondata);
                System.out.println(jsondata.containsKey("unionid"));
                if (!jsondata.containsKey("unionid")) {
                    // 被加密的数据
                    byte[] dataByte = Base64.decode(encryptedData);
                    // 加密秘钥
                    byte[] keyByte = Base64.decode(jsondata.get("session_key").toString());
                    // 偏移量
                    byte[] ivByte = Base64.decode(iv);
                    try {
                        // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
                        int base = 16;
                        if (keyByte.length % base != 0) {
                            int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                            byte[] temp = new byte[groups * base];
                            Arrays.fill(temp, (byte) 0);
                            System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                            keyByte = temp;
                        }
                        // 初始化
                        Security.addProvider(new BouncyCastleProvider());
                        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
                        SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
                        AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
                        parameters.init(new IvParameterSpec(ivByte));
                        cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
                        byte[] resultByte = cipher.doFinal(dataByte);
                        if (null != resultByte && resultByte.length > 0) {
                            String result = new String(resultByte, "UTF-8");
                            System.out.println(result);
                            JSONObject jSONObject = JSONObject.parseObject(result);
                            String unionId = jSONObject.get("unionId").toString();
                            jsondata.put("unionid", unionId);
                        }
                        return jsondata;
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (NoSuchPaddingException e) {
                        e.printStackTrace();
                    } catch (InvalidParameterSpecException e) {
                        e.printStackTrace();
                    } catch (IllegalBlockSizeException e) {
                        e.printStackTrace();
                    } catch (BadPaddingException e) {
                        e.printStackTrace();
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    } catch (InvalidKeyException e) {
                        e.printStackTrace();
                    } catch (InvalidAlgorithmParameterException e) {
                        e.printStackTrace();
                    } catch (NoSuchProviderException e) {
                        e.printStackTrace();
                    }
                } else {
                    jsondata.put("unionid", jsondata.get("unionid"));
                    jsondata.put("openid", jsondata.get("openid"));
                    jsondata.put("session_key", jsondata.get("session_key"));
                    jsondata.put(ConstantUtils.STATUS, ConstantUtils.ONE);
                    jsondata.put(ConstantUtils.MSG, ConstantUtils.SUCCESS);
                }
            } else {
                System.out.println("未获取到用户信息");
                jsondata.put("unionid", null);
                jsondata.put("openid", null);
                jsondata.put("session_key", null);
                jsondata.put(ConstantUtils.STATUS, ConstantUtils.ZERO);
                jsondata.put(ConstantUtils.MSG, ConstantUtils.SUCCESS);
            }
            return jsondata;
        }


    2019-10-18
    赞同
    回复 5
    • 王浩
      王浩
      2019-10-18
      2019-10-18
      回复
    • 王浩
      王浩
      2019-10-18回复王浩
      登录的时候,参数和code一起带过去,根据code获取到sessionkey后,再解密
      2019-10-18
      回复
    • 小程序@小萝卜报名
      小程序@小萝卜报名
      2019-10-18回复王浩
      可是这样,会不会当时微信加密的时候用的是旧的sessionkey,用code刷新了一下sessionkey,反而解密不出来了?我按照这种方法,会时不时的报错illegal
      2019-10-18
      回复
    • 小程序@小萝卜报名
      小程序@小萝卜报名
      2019-10-18
      你有没有统计过你这种方法,获取到的用户数据中空值的比例是多少?
      2019-10-18
      回复
    • 王浩
      王浩
      2019-10-21回复小程序@小萝卜报名
      还真没注意,我也再测试下看
      2019-10-21
      回复
登录 后发表内容
问题标签