作者:陳惠,叩丁狼教育高級(jí)講師。原創(chuàng)文章勺阐,轉(zhuǎn)載請(qǐng)注明出處。
在學(xué)習(xí)網(wǎng)頁(yè)授權(quán)之前矛双,我們先來(lái)了解下這次的需求:
我們的應(yīng)用中有一個(gè)用來(lái)顯示個(gè)人信息的頁(yè)面渊抽,當(dāng)微信用戶在微信app中打開(kāi)這個(gè)頁(yè)面,希望可以獲取到該用戶的頭像议忽,昵稱等信息懒闷,并顯示到該頁(yè)面中。如下圖所示:
如果用戶在微信客戶端中訪問(wèn)第三方網(wǎng)頁(yè)(我們的應(yīng)用),可以通過(guò)微信網(wǎng)頁(yè)授權(quán)機(jī)制愤估,來(lái)獲取用戶的基本信息(包括昵稱帮辟、性別、城市灵疮、國(guó)家等织阅,注意:手機(jī),QQ震捣,郵箱通過(guò)微信網(wǎng)頁(yè)授權(quán)是無(wú)法獲取的)荔棉。利用這些用戶信息,我們可以實(shí)現(xiàn)一些業(yè)務(wù)邏輯蒿赢,比如來(lái)源統(tǒng)計(jì)润樱、帳號(hào)綁定、用戶身份鑒權(quán)等功能羡棵。
OAuth2.0
微信的網(wǎng)頁(yè)授權(quán)是基于OAuth2.0協(xié)議的壹若,百科上對(duì)OAuth的介紹是:OAuth(開(kāi)放授權(quán))是一個(gè)開(kāi)放標(biāo)準(zhǔn),允許用戶讓第三方應(yīng)用訪問(wèn)該用戶在某一網(wǎng)站上存儲(chǔ)的私密的資源(如頭像皂冰,個(gè)人信息等)店展,而無(wú)需將用戶名和密碼提供給第三方應(yīng)用;而OAuth2.0則是OAuth協(xié)議的升級(jí)版秃流,但并不兼容老版本赂蕴。
實(shí)際上,現(xiàn)在很多企業(yè)都使用到OAuth2.0舶胀,比如支付寶概说,微信,QQ授權(quán)登錄等等嚣伐。
授權(quán)流程
微信開(kāi)發(fā)文檔中引導(dǎo)我們操作的流程是:
更詳細(xì)的流程如下糖赔,主要是利用一個(gè)code授權(quán)碼來(lái)進(jìn)行授權(quán):
AppID,AppSecret轩端,OpenID放典,Access_Token這些在之前的文章都已經(jīng)介紹過(guò)了,有需要的參考開(kāi)發(fā)教程(一)基茵,開(kāi)發(fā)教程(二)刻撒,開(kāi)發(fā)教程(四)文章。
特別注意:
1.本文中用到的Access_Token是專屬于網(wǎng)頁(yè)授權(quán)而使用的Access_Token憑據(jù)耿导,與之前其他接口用的Access_Token憑據(jù)是不同的,所以我們要通過(guò)另外一個(gè)接口來(lái)獲取網(wǎng)頁(yè)授權(quán)使用的Access_Token态贤。
2.網(wǎng)頁(yè)授權(quán)分兩種scope授權(quán)作用域
(1)scope為snsapi_base的網(wǎng)頁(yè)授權(quán)舱呻,是用來(lái)獲取進(jìn)入頁(yè)面的用戶的openid的,并且是靜默授權(quán)并自動(dòng)跳轉(zhuǎn)到回調(diào)頁(yè)的,也就是說(shuō)用戶完全感覺(jué)不到你在獲取他的信息箱吕,但只能獲取openid芥驳。
(2)scope為snsapi_userinfo的網(wǎng)頁(yè)授權(quán),是用來(lái)獲取用戶的基本信息的(包括openid茬高,頭像兆旬,昵稱,城市怎栽,性別等)丽猬,這種授權(quán)需要用戶手動(dòng)同意,無(wú)須關(guān)注公眾號(hào)熏瞄,就可在用戶同意后獲取該用戶的基本信息脚祟。
實(shí)現(xiàn)步驟
注意:服務(wù)號(hào)或者測(cè)試號(hào)才有網(wǎng)頁(yè)授權(quán)的功能權(quán)限
一:安裝微信web開(kāi)發(fā)者工具,待會(huì)用于調(diào)試頁(yè)面
下載地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140
二:配置授權(quán)域名强饮,設(shè)置該域名擁有網(wǎng)頁(yè)授權(quán)的權(quán)限(如果不設(shè)置由桌,就沒(méi)有權(quán)限使用網(wǎng)頁(yè)授權(quán))。
在接口權(quán)限列表找到網(wǎng)頁(yè)授權(quán)邮丰,點(diǎn)修改按鈕:
把域名填入到輸入框中:
確認(rèn)保存即可行您。
三:準(zhǔn)備好一個(gè)頁(yè)面,用于顯示用戶的詳細(xì)信息
我的頁(yè)面訪問(wèn)地址為http://huihui.mynatapp.cc/person.do剪廉,是通過(guò)controller請(qǐng)求轉(zhuǎn)發(fā)到個(gè)人信息頁(yè)面娃循。
代碼:
@RequestMapping("person")
public String person(){
return "person";
}
暫時(shí)的效果如圖所示,沒(méi)有顯示具體的用戶信息:
四:拼接網(wǎng)頁(yè)授權(quán)的url鏈接妈经,引導(dǎo)用戶打開(kāi)授權(quán)界面
格式如下:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
現(xiàn)在把我們具體的參數(shù)填上:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx59687be81dd3d388&redirect_uri=http://huihui.mynatapp.cc/person.do&response_type=code&scope=snsapi_userinfo#wechat_redirect
參數(shù)介紹:
appid: 公眾號(hào)的唯一標(biāo)識(shí)(從公眾號(hào)頁(yè)面中拷貝)
redirect_uri: 回調(diào)地址(現(xiàn)在用戶打開(kāi)的地址是open.weixin.qq.com的頁(yè)面淮野,頁(yè)面中會(huì)提示用戶是否同意授權(quán),當(dāng)用戶同意授權(quán)之后吹泡,就會(huì)跳轉(zhuǎn)到指定的回調(diào)地址上骤星,也就是我們自己的頁(yè)面)
response_type: 返回類型,請(qǐng)?zhí)顚?xiě)code(關(guān)于網(wǎng)頁(yè)授權(quán)的參數(shù)爆哑,統(tǒng)一填code即可)
scope: 應(yīng)用授權(quán)作用域(如之前介紹的兩種授權(quán)作用域洞难,填snsapi_base或者snsapi_userinfo)
state: 重定向到回調(diào)地址后會(huì)帶上state參數(shù),開(kāi)發(fā)者可以填寫(xiě)任意參數(shù)值(該參數(shù)不是必填揭朝,可傳可不傳队贱,有些業(yè)務(wù)操作需要自定義參數(shù)就可以用上)
#wechat_redirect:無(wú)論直接打開(kāi)還是做頁(yè)面302重定向時(shí)候,必須帶此參數(shù)
五:把地址拷貝到web開(kāi)發(fā)者工具中潭袱,查看效果
左邊的視圖出現(xiàn)了授權(quán)頁(yè)面柱嫌,這是因?yàn)槲沂褂玫氖莝nsapi_userinfo授權(quán)作用域,所以需要用戶同意授權(quán)屯换,此時(shí)用戶點(diǎn)擊確認(rèn)登錄后即可重定向到回調(diào)地址编丘。
可以看到与学,重定向到回調(diào)地址后,url上有兩個(gè)參數(shù)嘉抓,一個(gè)是code索守,這是一個(gè)授權(quán)碼,有了它之后我們才能做后面的操作抑片,另一個(gè)是state卵佛,就是之前說(shuō)的可以自定義參數(shù)傳遞,因?yàn)槲覜](méi)有設(shè)置state所以這里是空敞斋。
也可以使用手機(jī)來(lái)測(cè)試截汪,用微信來(lái)打開(kāi)鏈接,但微信的瀏覽器不易看出地址及參數(shù)的變化渺尘。
六:通過(guò)code來(lái)獲取網(wǎng)頁(yè)授權(quán)專用的access_token憑據(jù)
在請(qǐng)求的時(shí)候挫鸽,我們把a(bǔ)ppid,secret鸥跟,code這三個(gè)參數(shù)設(shè)置進(jìn)去即可丢郊。
public class WeChatUtil {
//公眾號(hào)唯一標(biāo)識(shí)
public static final String APPID = "wx59687be81dd3d388";
//公眾號(hào)的appsecret
public static final String APPSECRET = "d4624c36b6795d1d99dcf0547af5443d";
//獲取網(wǎng)頁(yè)授權(quán)accessToken的接口
public static final String GET_WEB_ACCESSTOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
/**
* 獲取網(wǎng)頁(yè)授權(quán)的AccessToken憑據(jù)
* @return
*/
public static JSONObject getWebAccessToken(String code){
String result = HttpUtil.get(GET_WEB_ACCESSTOKEN_URL.replace("APPID", APPID).replace("SECRET", APPSECRET).replace("CODE", code));
JSONObject json = JSONObject.parseObject(result);
return json;
}
若請(qǐng)求正確時(shí)返回的結(jié)果如下:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
參數(shù)介紹:
access_token:網(wǎng)頁(yè)授權(quán)接口調(diào)用憑證,注意:此access_token與基礎(chǔ)支持的access_token不同
expires_in:access_token接口調(diào)用憑證超時(shí)時(shí)間,單位(秒)
refresh_token:用戶刷新access_token
openid:用戶唯一標(biāo)識(shí)
scope:用戶授權(quán)的作用域
注意:
1.code作為換取access_token的票據(jù)医咨,每次用戶授權(quán)帶上的code將不一樣枫匾,code只能使用一次,5分鐘未被使用自動(dòng)過(guò)期拟淮。
2.access_token作為換取用戶信息的票據(jù)干茉,有效期為2個(gè)小時(shí),當(dāng)access_token超時(shí)后很泊,可以使用refresh_token進(jìn)行刷新角虫,refresh_token有效期為30天,當(dāng)refresh_token失效之后委造,需要用戶重新授權(quán)戳鹅。
七:通過(guò)access_token來(lái)獲取用戶的基本信息
接口地址:https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
//獲取用戶信息的接口
public static final String GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
/**
* 獲取用戶信息
*
*/
public static JSONObject getUserInfo(String accessToken,String openId){
String result = HttpUtil.get(GET_USERINFO_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID",openId));
JSONObject json = JSONObject.parseObject(result);
return json;
}
若請(qǐng)求正確時(shí)返回的結(jié)果如下:
{
"openid":" OPENID",
"nickname": "NICKNAME",
"sex":"1",
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege":[ "PRIVILEGE1" "PRIVILEGE2" ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
參數(shù)介紹:
openid:用戶的唯一標(biāo)識(shí)
nickname :用戶昵稱
sex:用戶的性別,值為1時(shí)是男性昏兆,值為2時(shí)是女性枫虏,值為0時(shí)是未知
province:用戶個(gè)人資料填寫(xiě)的省份
city:普通用戶個(gè)人資料填寫(xiě)的城市
country:國(guó)家
headimgurl:用戶頭像,最后一個(gè)數(shù)值代表正方形頭像大信朗(有0隶债、46、64跑筝、96死讹、132數(shù)值可選,0代表640*640正方形頭像)曲梗,用戶沒(méi)有頭像時(shí)該項(xiàng)為空回俐。若用戶更換頭像逛腿,原有頭像URL將失效。
privilege:用戶特權(quán)信息仅颇,json 數(shù)組,如微信沃卡用戶為(chinaunicom)
unionid:只有將公眾號(hào)綁定到微信開(kāi)放平臺(tái)帳號(hào)后碘举,才會(huì)出現(xiàn)該字段忘瓦。
八:整合Controller調(diào)用方法
@RequestMapping("person")
public String person(String code,Model model){
if(code!=null) {
//1.通過(guò)code來(lái)?yè)Q取access_token
JSONObject json = WeChatUtil.getWebAccessToken(code);
//獲取網(wǎng)頁(yè)授權(quán)access_token憑據(jù)
String webAccessToken = json.getString("access_token");
//獲取用戶openid
String openid = json.getString("openid");
//2.通過(guò)access_token和openid拉取用戶信息
JSONObject userInfo = WeChatUtil.getUserInfo(webAccessToken, openid);
//獲取json對(duì)象中的鍵值對(duì)集合
Set<Map.Entry<String, Object>> entries = userInfo.entrySet();
for (Map.Entry<String, Object> entry : entries) {
//把鍵值對(duì)作為屬性設(shè)置到model中
model.addAttribute(entry.getKey(),entry.getValue());
}
}
return "person";
}
為了便于理解,業(yè)務(wù)邏輯暫時(shí)寫(xiě)在controller中引颈,實(shí)際開(kāi)發(fā)時(shí)應(yīng)抽取到業(yè)務(wù)層耕皮。
九:頁(yè)面獲取model數(shù)據(jù)
<div class="weui-cells mt5">
<div class="weui-cell ">
<div class="weui-cell__bd">
昵稱
</div>
<div class="weui-cell__price">${nickname}</div>
</div>
<div class="weui-cell">
<div class="weui-cell__bd">
國(guó)家
</div>
<div class="weui-cell__price">${country}</div>
</div>
<div class="weui-cell">
<div class="weui-cell__bd">
所在城市
</div>
<div class="">${province} ${city}</div>
</div>
<div class="weui-cell weui-cell_access">
<div class="weui-cell__bd">
姓別
</div>
<div class="weui-cell__price">
<c:choose>
<c:when test="${sex==2}">
女
</c:when>
<c:when test="${sex==1}">
男
</c:when>
</c:choose>
</div>
</div>
效果:
從上圖中已經(jīng)看到頭像,昵稱蝙场,國(guó)家凌停,城市,性別都已經(jīng)從微信服務(wù)器獲取到了售滤,而手機(jī)罚拟,QQ,微信號(hào)這些內(nèi)容屬于用戶比較隱私的內(nèi)容完箩,微信是不會(huì)提供給我們的赐俗,我們只能讓用戶進(jìn)入頁(yè)面自己去補(bǔ)充其他的信息。