原创:微信小程序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

相关文章

Android实现悬浮按钮功能

《Android实现悬浮按钮功能》在很多场景中,我们希望在应用或系统任意界面上都能看到一个小的“悬浮按钮”(FloatingButton),用来快速启动工具、展示未读信息或快捷操作,所以本文给大家介绍... 目录一、项目概述二、相关技术知识三、实现思路四、整合代码4.1 Java 代码(MainActivi

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J

将Java项目提交到云服务器的流程步骤

《将Java项目提交到云服务器的流程步骤》所谓将项目提交到云服务器即将你的项目打成一个jar包然后提交到云服务器即可,因此我们需要准备服务器环境为:Linux+JDK+MariDB(MySQL)+Gi... 目录1. 安装 jdk1.1 查看 jdk 版本1.2 下载 jdk2. 安装 mariadb(my

使用Python实现一个优雅的异步定时器

《使用Python实现一个优雅的异步定时器》在Python中实现定时器功能是一个常见需求,尤其是在需要周期性执行任务的场景下,本文给大家介绍了基于asyncio和threading模块,可扩展的异步定... 目录需求背景代码1. 单例事件循环的实现2. 事件循环的运行与关闭3. 定时器核心逻辑4. 启动与停

基于Python实现读取嵌套压缩包下文件的方法

《基于Python实现读取嵌套压缩包下文件的方法》工作中遇到的问题,需要用Python实现嵌套压缩包下文件读取,本文给大家介绍了详细的解决方法,并有相关的代码示例供大家参考,需要的朋友可以参考下... 目录思路完整代码代码优化思路打开外层zip压缩包并遍历文件:使用with zipfile.ZipFil

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

SpringBoot中配置Redis连接池的完整指南

《SpringBoot中配置Redis连接池的完整指南》这篇文章主要为大家详细介绍了SpringBoot中配置Redis连接池的完整指南,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以... 目录一、添加依赖二、配置 Redis 连接池三、测试 Redis 操作四、完整示例代码(一)pom.

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思