1. 程式人生 > >Java開發微信小程式(二)獲取並解密小程式使用者和手機資訊

Java開發微信小程式(二)獲取並解密小程式使用者和手機資訊

第二篇 獲取並解密小程式的加密資訊包括使用者和手機資訊。

如果對其他的資訊幹興趣,還可以點選以下的連線

1.小程式登入獲取,小程式的openId和unionId。

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

https://blog.csdn.net/dafeige8/article/details/76019911

https://blog.csdn.net/zzm568599448/article/details/50516423