合肥網(wǎng)站建設(shè)信息搜索引擎廣告投放
05 | 如何安全、快速地接入OAuth 2.0?
構(gòu)建第三方軟件應(yīng)用
第一點(diǎn),注冊(cè)信息
小兔軟件的研發(fā)人員提前登錄到京東商家開(kāi)放平臺(tái)進(jìn)行手動(dòng)注冊(cè),以便后續(xù)使用這些注冊(cè)的相關(guān)信息來(lái)請(qǐng)求訪問(wèn)令牌。兔軟件需要先擁有自己的 app_id 和 app_serect 等信息,同時(shí)還要填寫自己的回調(diào)地址 redirect_uri、申請(qǐng)權(quán)限等信息。
第二點(diǎn),引導(dǎo)授權(quán)。
其實(shí)就是讓用戶為第三方軟件授權(quán),得到了授權(quán)之后,第三方軟件才可以代表用戶去訪問(wèn)數(shù)據(jù)。
第三點(diǎn),使用訪問(wèn)令牌。
拿到令牌后去使用令牌,才是第三方軟件的最終目的。
官方規(guī)范給出的使用訪問(wèn)令牌請(qǐng)求的方式,有三種,分別是:
- Form-Encoded Body Parameter(表單參數(shù))
- URI Query Parameter(URI 查詢參數(shù))
- Authorization Request Header Field(授權(quán)請(qǐng)求頭部字段)
建議你采用表單提交,也就是 POST 的方式來(lái)提交令牌,因?yàn)楸韱翁峤坏姆绞皆诒WC安全傳輸?shù)耐瑫r(shí),還不需要去額外處理 Authorization 頭部信息。
String protectedURl="http://localhost:8082/ProtectedServlet-ch03";
Map<String, String> paramsMap = new HashMap<String, String>();paramsMap.put("app_id","APPID_RABBIT");
paramsMap.put("app_secret","APPSECRET_RABBIT");
paramsMap.put("token",accessToken);String result = HttpURLClient.doPost(protectedURl,HttpURLClient.mapToStr(paramsMap));
第四點(diǎn),使用刷新令牌。
在小兔打單軟件收到訪問(wèn)令牌的同時(shí),也會(huì)收到訪問(wèn)令牌的過(guò)期時(shí)間 expires_in。一個(gè)設(shè)計(jì)良好的第三方應(yīng)用,應(yīng)該將 expires_in 值保存下來(lái)并定時(shí)檢測(cè);如果發(fā)現(xiàn) expires_in 即將過(guò)期,則需要利用 refresh_token 去重新請(qǐng)求授權(quán)服務(wù),以便獲取新的、有效的訪問(wèn)令牌。
服務(wù)市場(chǎng)中的第三方應(yīng)用軟件
作為第三方開(kāi)發(fā)者來(lái)構(gòu)建第三方軟件的時(shí)候,在授權(quán)碼環(huán)節(jié)除了要接收授權(quán)碼 code 值之外,還要接收用戶的訂購(gòu)相關(guān)信息,比如服務(wù)的版本號(hào)、服務(wù)代碼標(biāo)識(shí)等信息。
構(gòu)建受保護(hù)資源服務(wù)
比如說(shuō),訪問(wèn)頭像的 API、訪問(wèn)昵稱的 API。
基本都是以 Web API 為載體的形式進(jìn)行。因此呢,當(dāng)我們說(shuō)受保護(hù)資源被授權(quán)服務(wù)保護(hù)著時(shí),實(shí)際上說(shuō)的是授權(quán)服務(wù)最終保護(hù)的是這些 Web API.
//不同的權(quán)限對(duì)應(yīng)不同的操作
String[] scope = OauthServlet.tokenScopeMap.get(accessToken);StringBuffer sbuf = new StringBuffer();
for(int i=0;i<scope.length;i++){sbuf.append(scope[i]).append("|");
}if(sbuf.toString().indexOf("query")>0){queryGoods("");
}if(sbuf.toString().indexOf("add")>0){addGoods("");
}if(sbuf.toString().indexOf("del")>0){delGoods("");
}
不同的權(quán)限對(duì)應(yīng)不同的數(shù)據(jù)。
如果小兔軟件請(qǐng)求過(guò)來(lái)的一個(gè)訪問(wèn)令牌 access_token 的 scope 權(quán)限范圍只對(duì)應(yīng)了 Personal Data,那么包含該 access_token 值的請(qǐng)求就不能獲取到 Contact 和 Like 的信息,關(guān)于這部分的代碼,實(shí)際跟不同權(quán)限對(duì)應(yīng)不同操作的代碼類似。
不同的用戶對(duì)應(yīng)不同的數(shù)據(jù)。
多的場(chǎng)景卻是基于用戶屬性的。還是以小兔打單軟件為例,商家每次打印物流面單的時(shí)候,小兔打單軟件都要知道是哪個(gè)商家的訂單。這種情況下,商家為小兔軟件授權(quán),小兔軟件獲取的 access_token 實(shí)際上就包含了商家這個(gè)用戶屬性。
//不同的用戶對(duì)應(yīng)不同的數(shù)據(jù)
String user = OauthServlet.tokenMap.get(accessToken);
queryOrders(user);
總結(jié)
- 對(duì)于第三方軟件,比如小兔打單軟件來(lái)講,它的主要目的就是獲取訪問(wèn)令牌,使用訪問(wèn)令牌,這當(dāng)然也是整個(gè) OAuth 2.0 的目的,就是讓第三方軟件來(lái)做這兩件事。在這個(gè)過(guò)程中需要強(qiáng)調(diào)的是,第三方軟件在使用訪問(wèn)令牌的時(shí)候有三種方式,我們建議在平臺(tái)和第三方軟件約定好的前提下,優(yōu)先采用 Post 表單提交的方式。
- 受保護(hù)資源系統(tǒng),比如小兔軟件要訪問(wèn)開(kāi)放平臺(tái)的訂單數(shù)據(jù)服務(wù),它需要注意的是權(quán)限的問(wèn)題,這個(gè)權(quán)限范圍主要包括,不同的權(quán)限會(huì)有不同的操作,不同的權(quán)限也會(huì)對(duì)應(yīng)不同的數(shù)據(jù),不同的用戶也會(huì)對(duì)應(yīng)不同的數(shù)據(jù)。
原文