準(zhǔn)備知識(shí):
以上3點(diǎn)對(duì)于理解解密流程非常重要。
根據(jù)官方文檔,我梳理了大致的解密流程,如下:
重點(diǎn)在6、7、8三個(gè)環(huán)節(jié)。
AES解密三個(gè)參數(shù):
服務(wù)端解密流程:
下面結(jié)合小程序?qū)嵗f明解密流程:
微信登錄,獲取用戶信息
var that = this; wx.login({ success: function (res) { //微信js_code that.setData({wxcode: res.code}); //獲取用戶信息 wx.getUserInfo({ success: function (res) { //獲取用戶敏感數(shù)據(jù)密文和偏移向量 that.setData({encryptedData: res.encryptedData}) that.setData({iv: res.iv}) } }) } })
使用code換取3rdSessionId
var httpclient = require('../../utils/httpclient.js') VAR that = this //httpclient.req(url, data, method, success, fail) httpclient.req( 'http://localhost:8090/wxappservice/api/v1/wx/getSession', { apiName: 'WX_CODE', code: this.data.wxcode }, 'GET', function(result){ var thirdSessionId = result.data.data.sessionId; that.setData({thirdSessionId: thirdSessionId}) //將thirdSessionId放入小程序緩存 wx.setStorageSync('thirdSessionId', thirdSessionId) }, function(result){ console.log(result) } );
發(fā)起解密請(qǐng)求
//httpclient.req(url, data, method, success, fail) httpclient.req( 'http://localhost:8090/wxappservice/api/v1/wx/decodeUserInfo', { apiName: 'WX_DECODE_USERINFO', encryptedData: this.data.encryptedData, iv: this.data.iv, sessionId: wx.getStorageSync('thirdSessionId') }, 'GET', function(result){ //解密后的數(shù)據(jù) console.log(result.data) }, function(result){ console.log(result) } );
服務(wù)端解密實(shí)現(xiàn)(java)
/** * 解密用戶敏感數(shù)據(jù) * @param encryptedData 明文 * @param iv 加密算法的初始向量 * @param sessionId 會(huì)話ID * @return */ @Api(name = ApiConstant.WX_DECODE_USERINFO) @RequestMapping(value = "/api/v1/wx/decodeUserInfo", method = RequestMethod.GET, produces = "application/json") public Map<String,Object> decodeUserInfo(@RequestParam(required = true,value = "encryptedData")String encryptedData, @RequestParam(required = true,value = "iv")String iv, @RequestParam(required = true,value = "sessionId")String sessionId){ //從緩存中獲取session_key Object wxSessionObj = redisUtil.get(sessionId); if(null == wxSessionObj){ return rtnParam(40008, null); } String wxSessionStr = (String)wxSessionObj; String sessionKey = wxSessionStr.split("#")[0]; try { AES aes = new AES(); byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv)); if(null != resultByte && resultByte.length > 0){ String userInfo = new String(resultByte, "UTF-8"); return rtnParam(0, userInfo); } } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return rtnParam(50021, null); }
AES解密核心代碼
public 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 (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (NoSuchProviderException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
工作日 8:30-12:00 14:30-18:00
周六及部分節(jié)假日提供值班服務(wù)