吐血记录微信小程序授权获取Unionid及linux下使用bouncycastle解密用户数据 遇到的坑


声明:本文转载自https://my.oschina.net/yejunxi/blog/1802141,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

插播一条广告→2021 ByteDance字节跳动内推←各城市、各方向的岗位都有,大量招人!


背景

公司小程序上线了,发现系统无法拿到一些用户的UniondID。但是上线前的测试一切都是正常的。

坑1

经排查,发现一些用户通过下面的接口无法得到unionid

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

阅读https://developers.weixin.qq.com/miniprogram/dev/api/uinionID.html 得知,从未在关联公众号或小程序进行授权过的用户,是不会直接返回unionid的。要拿到这些用户的unionid需要以下3个数据

1.https://api.weixin.qq.com/sns/jscode2session返回的session_key

2. wx.getUserInfo且用户同意后返回的encryptedData和iv

使用以下代码可以解密出用户的信息

  import org.apache.commons.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.io.UnsupportedEncodingException; import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.Key; import java.security.NoSuchProviderException; import java.security.Security;   import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec;    public class AES {     public static boolean initialized = false;      public static void main(String[] args) throws InvalidAlgorithmParameterException, UnsupportedEncodingException {         String encryptedData = "";         String iv = "";         String sessionKey = "";          byte[] resultByte = AES.decrypt(Base64.decodeBase64(encryptedData),                 Base64.decodeBase64(sessionKey),                 Base64.decodeBase64(iv));         System.out.println(new String(resultByte,"utf-8"));     }      /**      * AES解密      *      * @param content 密文      * @return      * @throws InvalidAlgorithmParameterException      * @throws NoSuchProviderException      */     public static byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {         initialize();         try {             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");              Key sKeySpec = new SecretKeySpec(keyByte, "AES");               cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化              byte[] result = cipher.doFinal(content);              return result;         } catch (Exception e) {             e.printStackTrace();         }         return null;     }      public static void initialize() {         if (initialized) return;         Security.addProvider(new BouncyCastleProvider());         initialized = true;     }      //生成iv           public static AlgorithmParameters generateIV(byte[] iv) throws Exception {         AlgorithmParameters params = AlgorithmParameters.getInstance("AES");         params.init(new IvParameterSpec(iv));         return params;     }   }  

 

坑2,真正吐血的地方

使用以上的方法在我本机上面进行测试是没问题的,但是将项目部署上Linux上之后又出了一个问题

解密的时候抛异常:

java.security.NoSuchAlgorithmException - Cannot find any provider supporting AES/CBC/PKCS7Padding

我回头看代码,要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现,解密代码中确实也设置了。且本机也是可以解密的,本机和linux上的jdk均是官网下载的1.8版本,为什么Linux上就不行呢

//使用BouncyCastleProvider组件填充 Security.addProvider(new BouncyCastleProvider());

maven中也引用了bouncycastle

         <dependency>             <groupId>org.bouncycastle</groupId>             <artifactId>bcprov-jdk15on</artifactId>             <version>1.59</version>         </dependency>

 

排除代码问题的话很明显是环境问题了,linux上使用Security.addProvider(new BouncyCastleProvider());  不起效果。。。

 

那没办法了,只能手动改jre。步骤如下

1.把bcprov-jdk15on-1.59.jar 复制到jre目录中的/lib/ext

2.编辑/lib/security/java.security 

.... security.provider.1=sun.security.provider.Sun security.provider.2=sun.security.rsa.SunRsaSign security.provider.3=sun.security.ec.SunEC security.provider.4=com.sun.net.ssl.internal.ssl.Provider security.provider.5=com.sun.crypto.provider.SunJCE security.provider.6=sun.security.jgss.SunProvider security.provider.7=com.sun.security.sasl.Provider security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI security.provider.9=sun.security.smartcardio.SunPCSC  #在此加上这句代码 security.provider.x=org.bouncycastle.jce.provider.BouncyCastleProvider   .....

3.重启tomcat,解密成功了。。。

 

 

附一份检测是否支持bouncycastle的代码。方法:

import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.Cipher; import java.security.Security; public class TestB {      public static void main(String[] args) throws Exception {         Security.addProvider(new BouncyCastleProvider());          System.out.println("Attemptingto get a Cipher and encrypt...");         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");         System.out.println("OK");     } }

 

本文发表于2018年04月27日 22:38
(c)注:本文转载自https://my.oschina.net/yejunxi/blog/1802141,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1718 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1