• Java后端解密微信小程序手机号数据


    小程序端登录后,得到登录时获取的 code(仅可使用一次)

    App({
     onLaunch: function () {
           // 登录
           wx.login({
             success: res => {
               // 发送 res.code 到后台换取 openId, sessionKey, unionId
               console.log(res.code)
             }
               })
       }
    })

    2.后端访问微信登录凭证校验API
    小程序官方文档地址-登录凭证.
    通过官方提供的接口,获取到会话密钥session_key和openid
    https://api.weixin.qq.com/sns/jscode2session?appid=‘小程序id’&secret='小程序AppSecret '&js_code=‘步骤1中得到的code’&grant_type=authorization_code

    3.小程序请求客户授权获取手机号
    小程序官方文档地址-获取手机号
    (1)页面上增加一个按钮,用户点击后获取到敏感数据

    <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>

    (2)将e.detail传到后端

    Page({
      getPhoneNumber (e) {
        console.log(e.detail.errMsg)
        console.log(e.detail.iv)
        console.log(e.detail.encryptedData)
      }
    })
    

    4.结合sessionKey、encryptedData、iv三个参数,进行解密操作

    二、Java后端解密数据

    基于jdk1.8,低于1.8版本需要创建一个base64解密工具类

    1、实体类

    (1)微信手机号信息解密后的对象

    public class WeixinPhoneDecryptInfo {
    
        private String phoneNumber;
        private String purePhoneNumber;
        private int countryCode;
        private String weixinWaterMark;
        private WaterMark watermark;
    }
    public class WaterMark {
        private Long timestamp;// 时间戳做转换的时候,记得先乘以1000,再通过simpledateformat完成date类型转换
        private String appid;
    
        ...
    }

    2、解密工具类

    这一部分的代码,参考链接博客链接书写,感谢博主!
    实际使用中,由于特殊字符存在,可能导致base64解密失败,推荐引入org.apache.xmlbeans.impl.util.Base64,而不是java.util.Base64,感谢Prometheus_K反馈!

    import java.nio.charset.StandardCharsets;
    import java.security.AlgorithmParameters;
    import java.security.Key;
    import java.security.NoSuchAlgorithmException;
    import java.security.Security;
    import java.security.spec.InvalidParameterSpecException;
    import java.util.Base64;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    import com.alibaba.fastjson.JSON;
    
    public class AESForWeixinGetPhoneNumber {
    
        //加密方式
        private static String keyAlgorithm = "AES";
        //避免重复new生成多个BouncyCastleProvider对象,因为GC回收不了,会造成内存溢出
        //只在第一次调用decrypt()方法时才new 对象
        private static boolean initialized = false;
        //用于Base64解密
        private Base64.Decoder decoder = Base64.getDecoder();
    
        //待解密的数据
        private String originalContent;
        //会话密钥sessionKey
        private String encryptKey;
        //加密算法的初始向量
        private String iv;
    
        public AESForWeixinGetPhoneNumber(String originalContent,String encryptKey,String iv) {
            this.originalContent = originalContent;
            this.encryptKey = encryptKey;
            this.iv = iv;
        }
    
        /**
         * AES解密
         * 填充模式AES/CBC/PKCS7Padding
         * 解密模式128
         *
         * @return 解密后的信息对象
         */
        public WeixinPhoneDecryptInfo decrypt() {
            initialize();
            try {
                //数据填充方式
                //Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS7Padding”,”BC”);
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
                Key sKeySpec = new SecretKeySpec(decoder.decode(this.encryptKey), keyAlgorithm);
                // 初始化
                cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(decoder.decode(this.iv)));
                byte[]data = cipher.doFinal(decoder.decode(this.originalContent));
                String datastr = new String(data, StandardCharsets.UTF_8);
                return JSON.toJavaObject(JSON.parseObject(datastr),WeixinPhoneDecryptInfo.class);
            } catch (Exception e) {
                System.out.println(e.getMessage());
                System.out.println(222);
                return null;
            }
        }
    
        /**BouncyCastle作为安全提供,防止我们加密解密时候因为jdk内置的不支持改模式运行报错。**/
        private static void initialize() {
            if (initialized) {
                return;
            }
            Security.addProvider(new BouncyCastleProvider());
            initialized = true;
        }
    
        // 生成iv
        private static AlgorithmParameters generateIV(byte[] iv) throws NoSuchAlgorithmException, InvalidParameterSpecException {
            AlgorithmParameters params = AlgorithmParameters.getInstance(keyAlgorithm);
            params.init(new IvParameterSpec(iv));
            return params;
        }
    }

    需要引入的jar包

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.61</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk16</artifactId>
        <version>1.46</version>
    </dependency>

    测试

    public Object a(String encryptedData,String iv,String sessionKey){
            System.out.println("加密的敏感数据:" + encryptedData);
            System.out.println("初始向量:" + iv);
            System.out.println("会话密钥:" + sessionKey);
            String appId = "XXXXXXXXX";
            AESForWeixinGetPhoneNumber aes = new AESForWeixinGetPhoneNumber(encryptedData,sessionKey,iv);
            WeixinPhoneDecryptInfo info = aes.decrypt();
            if (null==info){
                System.out.println("error");
            }else {
                System.out.println(info.toString());
                if (!info.getWatermark().getAppid().equals(appId)){
                    System.out.println("wrong appId");
                }
            }
            return info;
        }

    WeixinPhoneDecryptInfo [phoneNumber=152XXXXXXXX, purePhoneNumber=152XXXXXXXX, countryCode=86, watermark={"appid":"XXXXXXXXXXXXX","timestamp":1600413039}, weixinWaterMark=null]

    原文链接: https://blog.csdn.net/weixin_42792301/article/details/101540668

  • 相关阅读:
    飞腾1500A 上面银河麒麟操作系统 进行远程以及添加用户的方法 linux xrdp
    centos7 安装Anaconda3及使用
    机器学习(ML)中文视频教程
    spring学习笔记(26)spring整合Quartz2持久化稳健任务调度
    Cocos2d-X中使用ProgressTimer实现一些简单的效果
    总结几点关于做互联网产品的思路
    norflash和nandflash电路
    存储过程
    USACO hamming 继续暴搜
    [原理分析]Linux下的栈溢出案例分析-GDB调试操练[1]
  • 原文地址:https://www.cnblogs.com/yrjns/p/13691483.html
Copyright © 2020-2023  润新知