吐血记录微信小程序授权获取Unionid及linux下使用bouncycastle解密用户数据 遇到的坑
背景
公司小程序上线了,发现系统无法拿到一些用户的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");
}
}
如果想用纯Js解密也是可以的,这里有一篇文章:https://www.cnblogs.com/cai-rd/p/6816849.html
吐血记录微信小程序授权获取Unionid及linux下使用bouncycastle解密用户数据 遇到的坑的更多相关文章
- 微信小程序无法获取UnionId的情况及处理
问题背景:做了微信小程序,一切都还正常,但是最后体验版放出去时,却发现很多用户无法绑定用户,后台返回:参数非法.经过多方排查,发现是微信拿到的code请求返回的数据里没有UnionId,也就是接口返回 ...
- 微信小程序授权获取用户详细信息openid
小程序获取用户的头像昵称openid之类 第一种使用wx.getUserInfo直接获取微信头像,昵称 wx.getUserInfo({ success: function (res) { that. ...
- 微信小程序授权 获取用户的openid和session_key【后端使用java语言编写】,我写的是get方式,目的是测试能否获取到微信服务器中的数据,后期我会写上post请求方式。
在这里给大家分享下我的心得,1.写代码前一定要对整个流程有个了解.我就是因为在先不了解整个过程中去ctrl+c+v他人的博客代码,花费很多无用的时间去处理还不知道能不能跑的起来的代码. 2.本人比较喜 ...
- 微信小程序授权获取手机号
wxml: <text>pages/logins/logins.wxml</text> // <button open-type="getPhoneNumber ...
- 【微信小程序】获取用户地理位置权限,二次请求授权,逆解析获取地址
摘要:微信小程序内获取用户地理位置信息授权,被拒绝后二次获取,获取权限后逆解析得到用户所在省市区等.. 场景:商城类小程序,在首页时需展示附近门店,即用户刚进入小程序时就需要获取到用户位置信息 ste ...
- 微信小程序如何获取openid
微信小程序如何获取openid wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId // ...
- 完整微信小程序授权登录页面教程
完整微信小程序授权登录页面教程 1.前言 微信官方对getUserInfo接口做了修改,授权窗口无法直接弹出,而取而代之是需要创建一个button,将其open-type属性绑定getUseInfo方 ...
- nodejs+koa+uniapp实现微信小程序登陆获取用户手机号及openId
nodejs+koa+uniapp实现微信小程序登陆获取用户手机号及openId 前言: 我准备用nodejs+koa+uniapp实现一款餐饮点单小程序,以及nodejs+koa+vue实现后端管理 ...
- 微信小程序验证码获取倒计时
wxml <button disabled='{{disabled}}' bindtap="goGetCode">{{code}}</button> js ...
随机推荐
- matplotlib正弦和余弦图
代码: # -*- coding: utf-8 -*- """ Created on Thu Jul 12 16:37:47 2018 @author: zhen &qu ...
- 位运算 leecode.389. 找不同
//给定两个字符串 s 和 t,它们只包含小写字母. //字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母. //请找出在 t 中被添加的字母 char findTheDifferenc ...
- Golang学习:sublime text3配置golang环境
最近导师让学习golang, 然后我就找了些有关golang的学习视频和网站. 昨天在电脑上下载了go tools, 之后在sublime上配置了golang的运行环境.By the way, 我的电 ...
- 2 OpenWrt路由器系统开发与网页设计
https://www.zhongkerd.com/news/content-729.html 摘 要: 目前商用WiFi路由器已应用到多个领域,商家通过给用户提供一个稳定免费WiFi热点达到吸引客户 ...
- springboot文件上传下载简单使用
springboot的文件上传比较简单 一.使用默认的Resolver:StandardServletMultipartResolver controller package com.mydemo.w ...
- nginx正则匹配
1.通用匹配规则 . 匹配除换行符以外的任意字符 \w 匹配字母.数字.下划线.汉字 \s 匹配任意的空白符 \d 匹配数字 ^ 匹配字符串的开始 $ 匹配字符串的结束 ...
- JS中的事件委托(事件代理)
一步一步来说说事件委托(或者有的资料叫事件代理) js中事件冒泡我们知道,子元素身上的事件会冒泡到父元素身上. 事件代理就是,本来加在子元素身上的事件,加在了其父级身上. 那就产生了问题:父级那么多子 ...
- HashMap源码解读(jdk1.8)
1.相关常量 默认初始化容量(大小) static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 最大容量 static final int M ...
- Java的String和StringBuilder
一.String 1.创建String对象的方法: String s1="haha"; String s2=new String(); String s3=new String(& ...
- gRPC源码分析(c++)
首先需要按照grpc官网上说的办法从github上下载源码,编译,然后跑一跑对应的测试代码.我分析的代码版本为v1.20.0. 在cpp的helloworld例子中,client端,第一个函数是创建c ...