第十一節(jié):OpenId萎河、UnionId荔泳、Session_key

同一個微信開放平臺下的相同主體的App、公眾號虐杯、小程序的unionid是相同的玛歌,這樣可判斷是否同一用戶
微信針對不同的用戶在不同的應用下都有唯一的一個openId
每個用戶對每個公眾號的OpenID是唯一的,對于不同公眾號擎椰,同一用戶的openid不同
?例如:
????同一用戶在移動應用(網(wǎng)頁web授權)支子,APP,公眾號确憨,小程序译荞,商戶等授權或關注后瓤的,openid是不同的
? ? 因此獲取在每種應用底下獲取到openid的url地址和請求參考也是不一樣的
? ? 應用名稱? ? ? ? ?URL? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 參數(shù)
? ? 小程序? ? ? ? ? ? ?https://api.weixin.qq.com/sns/jscode2session? ? ? ? ? ? ? ? ? appid、
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?secret吞歼、
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?js_code=WebAuthCode圈膏、
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? grant_type=authorization_code
? ? 微信網(wǎng)頁 ? ? ? ? https://api.weixin.qq.com/sns/oauth2/access_token? ? ??appid、
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?secret篙骡、
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?code=WebAuthCode稽坤、
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?grant_type=authorization_code
????注意:
? ? ? ? 1.這里得到的返回結(jié)果:除了openid,還有access_token
? ? ? ? 2.除了小程序外糯俗,其它應用開發(fā)(如:公眾號尿褪、web應用、商戶)獲取openid的url地址是一?樣得湘,只是appid和secret參數(shù)不同杖玲,如果是公眾號獲取openid,則參數(shù)填寫公眾號的openid和secret,同理商戶和其它應用淘正,appid和secret不同也就決定了在這個應用下的用戶對應的openid是不同的摆马。
? ? 東湖網(wǎng)上支付,采用了兩種支付方式:H5支付和公眾號支付鸿吆,都是采用“微信網(wǎng)頁”的同一URL來獲取webauthcode來交換openid囤采。這里面涉及到3個openid(用戶關注的公眾號openid,微信網(wǎng)頁移動應用openid惩淳,商戶openid)蕉毯,那不管是哪種支付,獲取的Openid都是由商戶的appid和secret參數(shù)來獲得這個用戶在商戶應用中的openid思犁。問題來了代虾,參見下面的"問題二"。
問題一:如果我們項目中有了個UserId,要能關聯(lián)同一微信平臺下的全部應用(移動應用抒倚、網(wǎng)站應用褐着、公眾帳號坷澡、小程序)托呕,怎么關聯(lián)呢?
問題二:在公眾號內(nèi)移動應用進行H5支付频敛,怎么確定是同一個用戶呢项郊?
open.weixin.qq.com的unionid機制。開放平臺和UnionId機制參考說明
使用unionid機制前提open.weixin.qq.com中注冊為開發(fā)者認證斟赚,綁定開發(fā)者賬號下的所有應用
如果不需要確定區(qū)分每種應用中的用戶是不是同一用戶着降,則不用理會unionid機制。?
小程序中獲取openId方法:
? ? 1.調(diào)用wx.login的時候會返回一個web authorize code
? ? 2.通過這個web authorize code去微信后臺獲取
? ? ? ? 后臺地址:https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
? ??????傳入appid,secret,JSCODE(web authorize code)去換取到openid,session_key以及unionid等信息
? ? ? ? 方式一:直接在小程序中調(diào)用(問題:https://api.weixin.qq.com 不在以下 request 合法域名列表中)
? ? ? ? ? ? 在調(diào)試階段拗军,我們可以在微信開發(fā)者工具中禁用這個警告任洞,考慮到小程序的發(fā)布版本蓄喇,
? ? ? ? ? ? 小程序中我們要設置自己的后臺合法域名,又不能同時設置兩個request合法域名? ? ? ? ? ??

小程序后臺設置后臺合法域名

? ? ? ? 方式二:通過我們自己的后臺去微信平臺URL獲取
? ? ? ? ????小程序獲取到web authorize code傳入到我們自己的后臺去獲取openId
? ? ? ? ? ? 官方:
? ? ? ? ? ? ? ? 1.小程序調(diào)用wx.login,wx.getUserInfo獲取臨時登錄憑證code交掏,并回傳到開發(fā)者服務器
? ? ? ? ? ? ? ? 2.開發(fā)者服務器以code換取用戶唯一標識openid會話密鑰session_key
? ??????????????之后開發(fā)者服務器可以根據(jù)用戶標識來生成自定義登錄態(tài)妆偏,用于后續(xù)業(yè)務邏輯中前后端交互時識別用戶身份。具體實現(xiàn)流程如下:? ? ?

安全使用openid和session_key

? ? 官方提醒
????????//正常返回的JSON數(shù)據(jù)包
????????{"openid":"OPENID","session_key":"SESSIONKEY",}
????????//滿足UnionID返回條件時盅弛,返回的JSON數(shù)據(jù)包?
? ? ? ? //滿足前提open.weixin.qq.com中注冊為開發(fā)者認證钱骂,綁定開發(fā)者賬號下的所有應用? ? ??
????????{"openid":"OPENID","session_key":"SESSIONKEY","unionid":"UNIONID"}
????????//錯誤時返回JSON數(shù)據(jù)包(示例為Code無效)
????????{"errcode":40029,"errmsg":"invalid code"}? ??
? ? 3.獲取加密信息
? ? 如果只是拿小程序的openid和unionid,則不用考慮這步挪鹏,
????因為上面第2步就可拿到openid和unionid(滿足unionid機制)

????在調(diào)用 wx.login,wx.getUserInfo都會返回一個對象见秽,這個對象有一個屬性叫encryptedData? ? ? ? ? ??

得到的encryptedData

這個字段的數(shù)據(jù)是加密的,所以我們可以通過解密的方式來得到原文信息讨盒,解密后為json解取,結(jié)構(gòu)如下:
? ?????{"openId":"OPENID","nickName":"NICKNAME","gender": GENDER,"city":"CITY","province":"PROVINCE","country":"COUNTRY","avatarUrl":"AVATARURL","unionId":"UNIONID","watermark": {"appid":"APPID","timestamp":TIMESTAMP }}
??新的數(shù)據(jù)解密方法?
? ??????總的來說還是原來的算法,還是原來的邏輯結(jié)構(gòu)返顺,不同的是解密方式肮蛹,
????????以前通過session_key得到iv,新方法是直接從前臺接口處得到iv來解密创南,所改變的也只是傳輸?shù)臄?shù)據(jù)
? ? ? ? 1.對稱解密使用的算法為 AES-128-CBC伦忠,數(shù)據(jù)采用PKCS#7填充。
? ? ? ? 2.對稱解密的目標密文為 Base64_Decode(encryptedData)稿辙。
? ? ? ? 3.對稱解密秘鑰 aeskey = Base64_Decode(session_key), aeskey 是16字節(jié)昆码。
? ? ? ? 4.對稱解密算法初始向量 為Base64_Decode(iv),其中iv由數(shù)據(jù)接口返回邻储。
詳細流程:
1.小程序客戶端調(diào)用wx.login赋咽,回調(diào)里面包含js_code。
2.然后將js_code發(fā)送到服務器A(開發(fā)者服務器),服務器A向微信服務器發(fā)起請求附帶js_code吨娜、appId脓匿、secretkey和grant_type參數(shù),以換取用戶的openid和session_key(會話密鑰)宦赠。
3.服務器A拿到session_key后陪毡,生成一個隨機數(shù)我們叫3rd_session,以3rdSessionId為key,以session_key + openid為value緩存到redis或memcached中;因為微信團隊不建議直接將session_key在網(wǎng)絡上傳輸勾扭,由開發(fā)者自行生成唯一鍵與session_key關聯(lián)毡琉。其作用是:
????將3rdSessionId返回給客戶端,維護小程序登錄態(tài)妙色。
????通過3rdSessionId找到用戶session_key和openid桅滋。
4.客戶端拿到3rdSessionId后緩存到storage,
5.通過wx.getUserIinfo可以獲取到用戶敏感數(shù)據(jù)encryptedData 身辨。
6.客戶端將encryptedData丐谋、3rdSessionId和偏移量一起發(fā)送到服務器A
7.服務器A根據(jù)3rdSessionId從緩存中獲取session_key
8.在服務器A使用AES解密encryptedData芍碧,從而實現(xiàn)用戶敏感數(shù)據(jù)解密
重點在6、7号俐、8三個環(huán)節(jié)师枣。
服務器端解密代碼示例
package com.iups.wx.wxservice;



importjava.io.UnsupportedEncodingException;

import java.security.AlgorithmParameters;

importjava.security.InvalidAlgorithmParameterException;

import java.security.InvalidKeyException;

importjava.security.NoSuchAlgorithmException;

importjava.security.NoSuchProviderException;

import java.security.Security;

importjava.security.spec.InvalidParameterSpecException;

import java.util.HashMap;

import java.util.Map;


import javax.crypto.BadPaddingException;

import javax.crypto.Cipher;

importjavax.crypto.IllegalBlockSizeException;

import javax.crypto.NoSuchPaddingException;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;


import net.sf.json.JSONObject;


import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.bouncycastle.util.Arrays;

import org.codehaus.xfire.util.Base64;


importcom.iups.wx.common.RemoteInterfaceAddress;

import com.iups.wx.util.HttpsClientUtil;


/**

?*微信小程序信息獲取

?*@author Administrator

?*@Date 2017年2月16日11:56:08

?*/

public class WXAppletUserInfo {



???/**

????*獲取微信小程序 session_key 和openid

????* @param code

????* @return

????*/

???public JSONObject getSessionKeyOropenid(String code){

???????//微信端登錄code值

???????String wxCode = code;

???????String requestUrl = RemoteInterfaceAddress.GETSESSIONKEYOROPENID;

???????Map requestUrlParam = newHashMap();

???????requestUrlParam.put("appid", RemoteInterfaceAddress.AppletAPPID);

???????requestUrlParam.put("secret",RemoteInterfaceAddress.AppletAppSecret);

???????requestUrlParam.put("js_code", wxCode);

???????requestUrlParam.put("grant_type","authorization_code");

???????JSONObject jsonObject = HttpsClientUtil.getInstance().sendGetRequest(requestUrl,requestUrlParam);

???????return jsonObject;

??? }


???/**

????*解密用戶敏感數(shù)據(jù)獲取用戶信息

????* @param sessionKey數(shù)據(jù)進行加密簽名的密鑰

????* @param encryptedData包括敏感數(shù)據(jù)在內(nèi)的完整用戶信息的加密數(shù)據(jù)

????* @param iv加密算法的初始向量

????* @return

????*/

???public JSONObject getUserInfo(String encryptedData,StringsessionKey,String iv){

???????//被加密的數(shù)據(jù)

???????byte[] dataByte = Base64.decode(encryptedData);

???????//加密秘鑰

???????byte[] keyByte = Base64.decode(sessionKey);

???????//偏移量

???????byte[] ivByte = Base64.decode(iv);


???????try {

?????????????? //如果密鑰不足16位,那么就補足.? 這個if 中的內(nèi)容很重要

???????????int base = 16;

???????????if (keyByte.length % base != 0) {

??????????????? int groups = keyByte.length /base + (keyByte.length % base != 0 ? 1 : 0);

??????????????? byte[] temp = new byte[groups *base];

??????????????? Arrays.fill(temp, (byte) 0);

??????????????? System.arraycopy(keyByte, 0,temp, 0, keyByte.length);

??????????????? keyByte = temp;

???????????}

???????????//初始化

???????????Security.addProvider(newBouncyCastleProvider());

???????????Cipher cipher =Cipher.getInstance("AES/CBC/PKCS7Padding","BC");

???????????SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");

???????????AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");

???????????parameters.init(new IvParameterSpec(ivByte));

???????????cipher.init(Cipher.DECRYPT_MODE, spec, parameters);//初始化

???????????byte[] resultByte = cipher.doFinal(dataByte);

???????????if (null != resultByte && resultByte.length > 0) {

??????????????? String result = newString(resultByte, "UTF-8");

??????????????? returnJSONObject.fromObject(result);

???????????}

???????} catch (NoSuchAlgorithmException e) {

???????????e.printStackTrace();

???????} catch (NoSuchPaddingException e) {

???????????e.printStackTrace();

???????} catch (InvalidParameterSpecException e) {

???????????e.printStackTrace();

???????} catch (IllegalBlockSizeException e) {

???????????e.printStackTrace();

???????} catch (BadPaddingException e) {

???????????e.printStackTrace();

???????} catch (UnsupportedEncodingException e) {

???????????e.printStackTrace();

???????} catch (InvalidKeyException e) {

???????????e.printStackTrace();

???????} catch (InvalidAlgorithmParameterException e) {

???????????e.printStackTrace();

???????} catch (NoSuchProviderException e) {

???????????e.printStackTrace();

???????}

???????return null;

??? }


}

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末萧落,一起剝皮案震驚了整個濱河市践美,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌找岖,老刑警劉巖陨倡,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異许布,居然都是意外死亡兴革,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門蜜唾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杂曲,“玉大人,你說我怎么就攤上這事袁余∏婵保” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵颖榜,是天一觀的道長棚饵。 經(jīng)常有香客問我,道長掩完,這世上最難降的妖魔是什么噪漾? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮且蓬,結(jié)果婚禮上欣硼,老公的妹妹穿的比我還像新娘。我一直安慰自己恶阴,他們只是感情好诈胜,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著存淫,像睡著了一般耘斩。 火紅的嫁衣襯著肌膚如雪沼填。 梳的紋絲不亂的頭發(fā)上桅咆,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機與錄音坞笙,去河邊找鬼岩饼。 笑死荚虚,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的籍茧。 我是一名探鬼主播版述,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼寞冯!你這毒婦竟也來了渴析?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吮龄,失蹤者是張志新(化名)和其女友劉穎俭茧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體漓帚,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡母债,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了尝抖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毡们。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖昧辽,靈堂內(nèi)的尸體忽然破棺而出衙熔,到底是詐尸還是另有隱情,我是刑警寧澤搅荞,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布青责,位于F島的核電站,受9級特大地震影響取具,放射性物質(zhì)發(fā)生泄漏脖隶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一暇检、第九天 我趴在偏房一處隱蔽的房頂上張望产阱。 院中可真熱鬧,春花似錦块仆、人聲如沸构蹬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庄敛。三九已至,卻和暖如春科汗,著一層夾襖步出監(jiān)牢的瞬間藻烤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留怖亭,地道東北人涎显。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像兴猩,于是被迫代替她去往敵國和親期吓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容