原创:微信小程序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实现将byte[]转换为File对象

《Java实现将byte[]转换为File对象》这篇文章将通过一个简单的例子为大家演示Java如何实现byte[]转换为File对象,并将其上传到外部服务器,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言1. 问题背景2. 环境准备3. 实现步骤3.1 从 URL 获取图片字节数据3.2 将字节数组

Win32下C++实现快速获取硬盘分区信息

《Win32下C++实现快速获取硬盘分区信息》这篇文章主要为大家详细介绍了Win32下C++如何实现快速获取硬盘分区信息,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实现代码CDiskDriveUtils.h#pragma once #include <wtypesbase

Nginx实现前端灰度发布

《Nginx实现前端灰度发布》灰度发布是一种重要的策略,它允许我们在不影响所有用户的情况下,逐步推出新功能或更新,通过灰度发布,我们可以测试新版本的稳定性和性能,下面就来介绍一下前端灰度发布的使用,感... 目录前言一、基于权重的流量分配二、基于 Cookie 的分流三、基于请求头的分流四、基于请求参数的分

Java捕获ThreadPoolExecutor内部线程异常的四种方法

《Java捕获ThreadPoolExecutor内部线程异常的四种方法》这篇文章主要为大家详细介绍了Java捕获ThreadPoolExecutor内部线程异常的四种方法,文中的示例代码讲解详细,感... 目录方案 1方案 2方案 3方案 4结论方案 1使用 execute + try-catch 记录

Python Excel实现自动添加编号

《PythonExcel实现自动添加编号》这篇文章主要为大家详细介绍了如何使用Python在Excel中实现自动添加编号效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍简单的说,就是在Excel中有一列h=会有重复

SpringBoot接收JSON类型的参数方式

《SpringBoot接收JSON类型的参数方式》:本文主要介绍SpringBoot接收JSON类型的参数方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、jsON二、代码准备三、Apifox操作总结一、JSON在学习前端技术时,我们有讲到过JSON,而在

Spring-AOP-ProceedingJoinPoint的使用详解

《Spring-AOP-ProceedingJoinPoint的使用详解》:本文主要介绍Spring-AOP-ProceedingJoinPoint的使用方式,具有很好的参考价值,希望对大家有所帮... 目录ProceedingJoinPoijsnt简介获取环绕通知方法的相关信息1.proceed()2.g

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Spring Security注解方式权限控制过程

《SpringSecurity注解方式权限控制过程》:本文主要介绍SpringSecurity注解方式权限控制过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、摘要二、实现步骤2.1 在配置类中添加权限注解的支持2.2 创建Controller类2.3 Us

Spring MVC跨域问题及解决

《SpringMVC跨域问题及解决》:本文主要介绍SpringMVC跨域问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录跨域问题不同的域同源策略解决方法1.CORS2.jsONP3.局部解决方案4.全局解决方法总结跨域问题不同的域协议、域名、端口