原创:微信小程序java实现AES解密并获取unionId

2024-08-28 08:32

本文主要是介绍原创:微信小程序java实现AES解密并获取unionId,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如果大家使用小程序的同时还在使用公众号的话,可能会用到unionId这种功能,由于公司业务需要,我们需要使用unionId,具体使用方法,请参考微信开放平台的说明,但是在微信小程序的文档中只给出了部分语言实现的源码,竟然没有Java的,小程序的开发人员是有多么懒。难道大家都不用java写后台???


什么鬼,然后开始了各种AES踩坑之路,其实参考了很多的网上的教程,再次不能一一列出来给大家了,(因为我写这篇文章的时候,已经是解决问题一周以后了),也收到管理员的很多帮助,再次写个帖子回馈大家吧,在此只列出unionId的解密方式,如果有什么问题,联系我或者回帖都可以。


另外稍加吐槽一下, 
https 不要用startcom提供的免费证书! 
https 不要用startcom提供的免费证书! 
https 不要用startcom提供的免费证书!


重要的事情说三遍!!!!


AES.java

[java]  view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:12px;">import org.apache.commons.codec.binary.Base64;  
  2. import org.bouncycastle.jce.provider.BouncyCastleProvider;  
  3. import javax.crypto.BadPaddingException;  
  4. import javax.crypto.Cipher;  
  5. import javax.crypto.IllegalBlockSizeException;  
  6. import javax.crypto.NoSuchPaddingException;  
  7. import javax.crypto.spec.IvParameterSpec;  
  8. import javax.crypto.spec.SecretKeySpec;  
  9. import java.security.*;  
  10. public class AES {  
  11.     public static boolean initialized = false;  
  12.     /** 
  13.      * AES解密 
  14.      * @param content 密文 
  15.      * @return 
  16.      * @throws InvalidAlgorithmParameterException 
  17.      * @throws NoSuchProviderException 
  18.      */  
  19.     public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {  
  20.         initialize();  
  21.         try {  
  22.             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");  
  23.             Key sKeySpec = new SecretKeySpec(keyByte, "AES");  
  24.             cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化  
  25.             byte[] result = cipher.doFinal(content);  
  26.             return result;  
  27.         } catch (NoSuchAlgorithmException e) {  
  28.             e.printStackTrace();  
  29.         } catch (NoSuchPaddingException e) {  
  30.             e.printStackTrace();  
  31.         } catch (InvalidKeyException e) {  
  32.             e.printStackTrace();  
  33.         } catch (IllegalBlockSizeException e) {  
  34.             e.printStackTrace();  
  35.         } catch (BadPaddingException e) {  
  36.             e.printStackTrace();  
  37.         } catch (NoSuchProviderException e) {  
  38.             // TODO Auto-generated catch block  
  39.             e.printStackTrace();  
  40.         } catch (Exception e) {  
  41.             // TODO Auto-generated catch block  
  42.             e.printStackTrace();  
  43.         }  
  44.         return null;  
  45.     }  
  46.     public static void initialize(){  
  47.         if (initialized) return;  
  48.         Security.addProvider(new BouncyCastleProvider());  
  49.         initialized = true;  
  50.     }  
  51.     //生成iv  
  52.     public static AlgorithmParameters generateIV(byte[] iv) throws Exception{  
  53.         AlgorithmParameters params = AlgorithmParameters.getInstance("AES");  
  54.         params.init(new IvParameterSpec(iv));  
  55.         return params;  
  56.     }  
  57. }</span>  

WxPKCS7Encoder.java

[javascript]  view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:12px;">import java.nio.charset.Charset;  
  2. import java.util.Arrays;  
  3. /** 
  4. * Created by Kevin Dong on 2017/1/5. 
  5. */  
  6. public class WxPKCS7Encoder {  
  7.     private static final Charset CHARSET = Charset.forName("utf-8");  
  8.     private static final int BLOCK_SIZE = 32;  
  9.     /** 
  10.      * 获得对明文进行补位填充的字节. 
  11.      * 
  12.      * @param count 需要进行填充补位操作的明文字节个数 
  13.      * @return 补齐用的字节数组 
  14.      */  
  15.     public static byte[] encode(int count) {  
  16.         // 计算需要填充的位数  
  17.         int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);  
  18.         if (amountToPad == 0) {  
  19.             amountToPad = BLOCK_SIZE;  
  20.         }  
  21.         // 获得补位所用的字符  
  22.         char padChr = chr(amountToPad);  
  23.         String tmp = new String();  
  24.         for (int index = 0; index < amountToPad; index++) {  
  25.             tmp += padChr;  
  26.         }  
  27.         return tmp.getBytes(CHARSET);  
  28.     }  
  29.     /** 
  30.      * 删除解密后明文的补位字符 
  31.      * 
  32.      * @param decrypted 解密后的明文 
  33.      * @return 删除补位字符后的明文 
  34.      */  
  35.     public static byte[] decode(byte[] decrypted) {  
  36.         int pad = decrypted[decrypted.length - 1];  
  37.         if (pad < 1 || pad > 32) {  
  38.             pad = 0;  
  39.         }  
  40.         return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);  
  41.     }  
  42.     /** 
  43.      * 将数字转化成ASCII码对应的字符,用于对明文进行补码 
  44.      * 
  45.      * @param a 需要转化的数字 
  46.      * @return 转化得到的字符 
  47.      */  
  48.     public static char chr(int a) {  
  49.         byte target = (byte) (a & 0xFF);  
  50.         return (char) target;  
  51.     }  
  52. }</span>  

调用方法解密如下:

[java]  view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:12px;">WechatOpenIdRes wechatInfo  = getWehatInfoByCode(code);  
  2.         if(wechatInfo != null && wechatInfo.isOk()){  
  3.             boolean isNew = true;  
  4.             try {  
  5.                 AES aes = new AES();  
  6.                 byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(wechatInfo.getSession_key()), Base64.decodeBase64(iv));  
  7.                 if(null != resultByte && resultByte.length > 0){  
  8.                      String userInfo = new String(WxPKCS7Encoder.decode(resultByte) ,"UTF-8");  
  9.                     WxInfo wxInfo = GsonUtil.fromGson(userInfo, WxInfo.class);  
  10.                     if(wxInfo != null) {  
  11.                         logger.debug("xxxxxunionid===="+wxInfo.getUnionId());  
  12.                     }  
  13.                 }  
  14.             } catch (InvalidAlgorithmParameterException e) {  
  15.                 e.printStackTrace();  
  16.             } catch (Exception e) {  
  17.                 e.printStackTrace();  
  18.             }</span>  

编译环境为java1.8 
另外我引入的support 包为 
bcprov-jdk16-139.jar 此包已上传附件, 
顺带附上我试用的小程序js中的代码吧,

[javascript]  view plain copy
  1. <span style="font-family:Microsoft YaHei;font-size:12px;">var code ="";  
  2. wechat.login()  
  3.       .then(function(res){  
  4.         code = res.code;          
  5.       })  
  6.       .then(function(){  
  7.         return wechat.getUserInfo();  
  8.       })  
  9.       .then(function(res){  
  10. var encryptedData = res.encryptedData  
  11. var iv = res.iv;  
  12. return userservice.getUserToken(code,encryptedData,iv);  
  13.       })</span>  

上面的代码使用了promise,其中最后一句userservice.getUserToken为请求服务器的方法,参数为获取到的code+加密内容+初始化向量

有什么问题可以联系我。

qq:403125094

源码下载地址:http://www.wxapp-union.com/portal.php?mod=view&aid=1189

这篇关于原创:微信小程序java实现AES解密并获取unionId的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1114256

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三