第二篇 獲取並解密小程序的加密信息包括用戶和手機信息。
如果對其他的信息幹興趣,還可以點擊以下的連接
2.獲取並解密小程序的加密信息包括用戶和手機信息。
3.用小程序給用戶推送服務消息。
4.給綁定小程序而且又關注微信公衆號的用戶推送公衆號消息。
好的,開始我們的獲取和解密操作吧,主要有以下這些步驟
1.小程序客戶端調用wx.login(),獲取到票據code。(請參照第一篇)
2.然後將code發送到Java服務器,接下來在java後臺我們用保存好的AppID,AppSecret和傳遞過來的code,調用 code2Session 接口獲取openId,unionId和session_key(會話密鑰)。(請參照第一篇)
3.服務器拿到session_key後,會將它保存在服務器的緩存中;因爲微信團隊不建議直接將session_key在網絡上傳輸,由開發者自行生成唯一鍵與session_key關聯。其作用是維護小程序登錄態,如果用戶重新登錄或超時需要重新獲取session_key。(請參照第一篇)
4.1通過wx.getUserInfo可以獲取到用戶敏感數據encryptedData 。
調用前需要 用戶授權,彈出授權窗口,請使用 <button open-type="getUserInfo"/>
// 獲取用戶信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已經授權,可以直接調用 getUserInfo 獲取頭像暱稱,不會彈框
wx.getUserInfo({
success: res => {
console.log(res.userInfo.avatarUr);
console.log(res.userInfo);
}
})
}
}
})
4.2通過getPhoneNumber可以獲取到用戶敏感數據encryptedData 。
獲取微信用戶綁定的手機號,需先調用wx.login接口。
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
getPhoneNumber(e) {
console.log(e)
console.log(e.detail.errMsg)
console.log(e.detail.iv)
console.log(e.detail.encryptedData)
}
5.客戶端將加密數據encryptedData、session_key和偏移量iv一起發送到Java服務器
//將獲取到的iv和encryptedData發送到java後臺解密
wx.request({
url: "https://www.test.com/app/interface/miniprogram/miniprogramDecrypt",
data: {
head: {},
body: {
encryptedData: e.detail.encryptedData,
iv: e.detail.iv,
openId: "E67148F6DB22D1E53E3B760B2B556FD5C2701F0AC0CF8987D71D6E4711FCBF737E099DA6057C35DC13D0D886066610E6"
}
},
method: "POST",
header: {
'content-type': 'application/json',
},
success: function (res) {
console.log(res);
},
fail: function (error) {
console.log(error);
}
})
6.Java服務器接受到傳遞過來的參數encryptedData和偏移量iv,在從緩存中獲取session_key
public class MiniprogramDecryptDataInterfaceAction extends BaseInterfaceAction {
private static final Logger logger = LoggerFactory.getLogger(MiniprogramDecryptDataInterfaceAction.class);
@Override
public String execute() throws Exception {
logger.debug("小程序加密數據解密-----開始");
// 獲取前端傳遞的數據
HttpServletRequest request = this.getRequest();
String appId = "你的開發者Id";
String encryptedData = request.getParameter("encryptedData");
//用戶唯一標識,通過openId獲取預先從微信端取到的session_key
String openId = request.getParameter("openId");
String iv = request.getParameter("iv");
//調用通用方法解密
String decryptData = MiniprogramUtil.getDecryptedData(appId, openId, encryptedData, iv);
logger.debug("小程序加密數據解密結束返回數據:" + decryptData);
return null;
}
}
/**
* 對加密數據進行解密並返回結果
*
* @param mByte
* @return
* @throws Exception
*/
public static String getDecryptedData(String appId, String openId, String encryptedData, String iv)
throws Exception {
String result = "";
//根據openId從session中取得sessionKey
String sessionKey = getSessionKey(openId);
if (StringUtils.isNotBlank(appId)) {
//根據appId和sessionKey對加密數據進行解密
WXBizDataCrypt pc = new WXBizDataCrypt(appId, sessionKey);
result = pc.decryptData(encryptedData, iv);
}
return result;
}
7.Java服務器使用AES解密方法對encryptedData進行解密,從而實現用戶敏感數據解密
解密需要參考的文章:
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
/**
* 對微信小程序用戶加密數據的解密
*
* @author 網行天下
*/
public class WXBizDataCrypt {
private String appid;
private String sessionKey;
public WXBizDataCrypt(String appid, String sessionKey) {
this.appid = appid;
this.sessionKey = sessionKey;
}
/**
* 檢驗數據的真實性,並且獲取解密後的明文.
*
* @param encryptedData
* string 加密的用戶數據
* @param iv
* string 與用戶數據一同返回的初始向量
*
* @return data string 解密後的原文
* @throws InvalidAlgorithmParameterException
* @throws UnsupportedEncodingException
*/
public String decryptData(String encryptedData, String iv) throws Exception {
String userInfo = "";
if (StringUtils.length(sessionKey) != 24) {
return "ErrorCode::$IllegalAesKey;";
}
// 對稱解密祕鑰 aeskey = Base64_Decode(session_key), aeskey 是16字節。
byte[] aesKey = Base64.decodeBase64(sessionKey);
if (StringUtils.length(iv) != 24) {
return "ErrorCode::$IllegalIv;";
}
// 對稱解密算法初始向量 爲Base64_Decode(iv),其中iv由數據接口返回。
byte[] aesIV = Base64.decodeBase64(iv);
// 對稱解密的目標密文爲 Base64_Decode(encryptedData)
byte[] aesCipher = Base64.decodeBase64(encryptedData);
byte[] resultByte = AESUtils.decrypt(aesCipher, aesKey, aesIV);
if (null != resultByte && resultByte.length > 0) {
userInfo = new String(resultByte, "UTF-8");
}
return userInfo;
}
}
用到maven依賴
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.32</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.55</version>
</dependency>
8.本文遇到的一些問題和參考文獻
https://blog.csdn.net/will_awoke/article/details/79155182