日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【实例图文详解】OAuth 2.0 for Web Server Applications

發布時間:2025/3/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【实例图文详解】OAuth 2.0 for Web Server Applications 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接:http://blog.csdn.net/hjun01/article/details/42032841? ? ??

?

?OAuth 2.0 for Web Server Applications, verifying a user's?Android?in-app subscription

????????

??????? 在寫本文之前先說些題外話。

? ? ? ? 前段時間游戲急于在GoolePlay上線,明知道如果不加Auth2.0的校驗是不安全的還是暫時略過了這一步,果然沒幾天就發現后臺記錄與玩家實際付費不太一致,懷疑有玩家盜刷游戲元寶等,并且真實的走過了GooglePlay的所有支付流程完成道具兌換,時間一長嚴重性可想而知。經過查閱大量google官方文檔后把代碼補上,并在這里記錄下OAuth 2.0 的使用,Google提供了OAuth2.0的好幾種使用用途,每種使用方法都有些不同,具體可以看下這篇博客。在這里只寫OAuth 2.0 for Web Server Applications的使用,涉及refresh_token, access_token等的獲取和使用,以及如何向google發送GET和POST請求等,最終完成用戶在安卓應用內支付購買信息的校驗。

? ? ? ? 先貼下關于Using OAuth 2.0 for Web Server Applications的解釋的谷歌官方原文:

? ? ? ? The authorization sequence begins when your application redirects a browser to a Google URL; the URL includes query parameters that indicate the type of access being requested. As in other scenarios, Google handles user authentication, session selection, and user consent. The result is an authorization code, which Google returns to your application in a query string.
? ? ? ? After receiving the authorization code, your application can exchange the code (along with a client ID and client secret) for an access token and, in some cases, a refresh token.
? ? ? ? The application can then use the access token to access a Google API.
? ? ? ? If a refresh token is present in the authorization code exchange, then it can be used to obtain new access tokens at any time. This is called offline access, because the user does not have to be present at the browser when the application obtains a new access token.

通過原文和圖解我們可以知道這樣一個流程(下文會詳細說明):

? ? ? ??一. 在Google Developer Console中創建一個?Web Application賬戶,得到client_id,client_secret 和?redirect_uri,這3個參數后邊步驟常用到(此為前提)

? ? ? ? 二. 獲取Authorization code?

? ? ? ? 三. 利用code 獲取access_token,refresh_token

? ? ? ? 四. 進一步可利用refresh_token獲取新的access_token

? ? ? ? 五. 使用access_token 調用Google API 達到最終目的(如果access_token過時,回到第四步)

? ? ? ? 需注意的是:在第三步操作,當我們第一次利用code獲取access_token時,谷歌會同時返回給你一個refresh_token,以后再次用code獲取access_token操作將不會再看到refresh_token,所以一定要保存下來。這個refresh_token是長期有效的,如果沒有明確的被應用管理者撤銷是不會過期的,而access_token則只有3600秒的時效,即1個小時,那么問題來了,access_token和refresh_token是什么關系?很明顯的,我們最終是要使用access_token 去調用Google API,而access_token又有時效限制,所以當access_token過期后,我們可以用長效的refresh_token去再次獲取access_token,并且可以可以在任何時間多次獲取,沒有次數限制。其實當我們得到refresh_token后,就是一個轉折點。 ?

?

? ? ? ? 下面詳細分解步驟:

一、在Google Developer Console中創建一個Web application賬戶

? ? (這里使用的是新版的Google Developer Console頁面,其實可在Account settings中設置為中文顯示~)

? ? ? ??

? ? ? ? 其中4.可以隨意填寫。創建完成后可以看下下圖所示:

?

? ? ? ? 在這里我們拿到3個關鍵參數:?client_id,client_secret,redirect_uris,,于下邊步驟。

可能會有人有疑問,怎么就能確定在google developer console 建立的project就于Googleplay上線的安卓應用有關聯呢?為什么可以用這些參數得來的access_token去調用谷歌API?其實在Googleplay發布應用時就有關聯project的操作,之后創建project的人可以給其他谷歌賬戶授權,這樣其他谷歌賬戶可以在自己的developer console頁面直接看到該project和以下的web application等, 并且可在下一步操作中登錄自己的谷歌賬戶獲取code。

?

二. 獲取Authorization code

https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher &response_type=code &access_type=offline &redirect_uri={REDIRECT_URIS} &client_id={CLIENT_ID}

? ? ? ? 我們需要將這個URL以瀏覽器的形式打開,這時會跳出提示你Sign in with your Google Account,然后在用有project授權的谷歌賬戶登錄,地址欄會出現我們所需的code。例如:https://www.example.com/oauth2callback?code=4/CpVOd8CljO_gxTRE1M5jtwEFwf8gRD44vrmKNDi4GSS.kr-GHuseD-oZEnp6UADFXm0E0MD3FlAI

?

三. 利用code 獲取access_token,refresh_token

https://accounts.google.com/o/oauth2/token? code={CODE} &client_id={CLIENT_ID} &client_secret={CLIENT_SECRET} &redirect_uri={REDIRECT} &grant_type=authorization_code

? ? ? ? 我們這一步的目的是獲取refresh_token,只要有了這個長效token,access_token是隨時可以獲取的,第一次發起請求得到的JSON字符串如下所示,以后再請求將不再出現refresh_token,要保存好。expires_in是指access_token的時效,為3600秒。

{

"access_token": "ya29.3gC2jw5vm77YPkylq0H5sPJeJJDHX93Kq8qZHRJaMlknwJ85595eMogL300XKDOEI7zIsdeFEPY6zg", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "1/FbQD448CdDPfDEDpCy4gj_m3WDr_M0U5WupquXL_o" }

? ? ? ???

四. 進一步可利用refresh_token獲取新的access_token

https://accounts.google.com/o/oauth2/token? grant_type=refresh_token &client_id={CLIENT_ID} &client_secret={CLIENT_SECRET} &refresh_token={REFRESH_TOKEN}

? ? ? ? 這里我們要向谷歌發起POST請求,Java代碼如下:

[java]?view plain?copy?print?
  • /**?獲取access_token?**/??
  • private?static?Map<String,String>?getAccessToken(){??
  • ????final?String?CLIENT_ID?=?"填入你的client_id";??
  • ????final?String?CLIENT_SECRET?=?"填入你的client_secret";??
  • ????final?String?REFRESH_TOKEN?=?"填入上一步獲取的refresh_token";??
  • ????Map<String,String>?map?=?null;??
  • ????try?{??
  • ????????/**?
  • ?????????*?https://accounts.google.com/o/oauth2/token?refresh_token={REFRESH_TOKEN}?
  • ?????????*?&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&grant_type=refresh_token?
  • ?????????*/??
  • ????????URL?urlGetToken?=?new?URL("https://accounts.google.com/o/oauth2/token");??
  • ????????HttpURLConnection?connectionGetToken?=?(HttpURLConnection)?urlGetToken.openConnection();??
  • ????????connectionGetToken.setRequestMethod("POST");??
  • ????????connectionGetToken.setDoOutput(true);??
  • ????????//?開始傳送參數??
  • ????????OutputStreamWriter?writer??=?new?OutputStreamWriter(connectionGetToken.getOutputStream());??
  • ????????writer.write("refresh_token="+REFRESH_TOKEN+"&");??
  • ????????writer.write("client_id="+CLIENT_ID+"&");???
  • ????????writer.write("client_secret="+CLIENT_SECRET+"&");??
  • ????????writer.write("grant_type=refresh_token");???
  • ????????writer.close();??
  • ????????//若響應碼為200則表示請求成功??
  • ????????if(connectionGetToken.getResponseCode()?==?HttpURLConnection.HTTP_OK){??
  • ????????????StringBuilder?sb?=?new?StringBuilder();??
  • ????????????BufferedReader?reader?=?new?BufferedReader(??
  • ????????????????????new?InputStreamReader(connectionGetToken.getInputStream(),?"utf-8"));??
  • ????????????String?strLine?=?"";??
  • ????????????while((strLine?=?reader.readLine())?!=?null){??
  • ????????????????sb.append(strLine);??
  • ????????????}??
  • ????????????//?取得谷歌回傳的信息(JSON格式)??
  • ????????????JSONObject?jo?=?JSONObject.fromObject(sb.toString());??
  • ????????????String?ACCESS_TOKEN?=?jo.getString("access_token");???
  • ????????????Integer?EXPIRES_IN?=?jo.getInt("expires_in");??
  • ????????????map?=?new?HashMap<String,String>();??
  • ????????????map.put("access_token",?ACCESS_TOKEN);??
  • ????????????map.put("expires_in",?String.valueOf(EXPIRES_IN));??
  • ????????????//?帶入access_token的創建時間,用于之后判斷是否失效??
  • ????????????map.put("create_time",String.valueOf((new?Date().getTime())?/?1000));??
  • ????????????logger.info("包含access_token的JSON信息為:?"+jo);??
  • ????????}??
  • ????}?catch?(MalformedURLException?e)?{??
  • ????????logger.error("獲取access_token失敗,原因是:"+e);??
  • ????????e.printStackTrace();??
  • ????}?catch?(IOException?e)?{??
  • ????????logger.error("獲取access_token失敗,原因是:"+e);??
  • ????????e.printStackTrace();??
  • ????}??
  • ????return?map;??
  • }??

  • 五. 使用access_token 調用Google API 達到最終目的(如果access_token過時,回到第四步)

    ? ? ? ? 在這里我所需要獲取的是我在應用內給GooglePlay支付的購買信息,此類信息包含以下幾個屬性:(可參考Google Play Developer API下的Purchases.products)

    ? ? ? ? A ProductPurchase resource indicates the status of a user's inapp product purchase.

    {"kind": "androidpublisher#productPurchase", ? "purchaseTimeMillis": long, ? "purchaseState": integer, (purchased:0 cancelled:1,我們就是依靠這個判斷購買信息) ? "consumptionState": integer, ? "developerPayload": string }

    ? ? ? ? 帶著access_token參數向GoogleApi發起GET請求,Java代碼如下:

    [java]?view plain?copy?print?
  • private?static?Map<String,String>?cacheToken?=?null;//設置靜態變量,用于判斷access_token是否過期??
  • ??
  • public?static?GooglePlayBuyEntity?getInfoFromGooglePlayServer(String?packageName,String?productId,?String?purchaseToken)?{??
  • ????if(null?!=?cacheToken){??
  • ????????Long?expires_in?=?Long.valueOf(cacheToken.get("expires_in"));?//?有效時長??
  • ????????Long?create_time?=?Long.valueOf(cacheToken.get("create_time"));?//?access_token的創建時間??
  • ????????Long?now_time?=?(new?Date().getTime())?/?1000;??
  • ????????if(now_time?>?(create_time?+?expires_in?-?300)){?//?提前五分鐘重新獲取access_token??
  • ????????????cacheToken?=?getAccessToken();??
  • ????????}??
  • ????}else{??
  • ????????cacheToken?=?getAccessToken();??
  • ????}??
  • ??????
  • ????String?access_token?=?cacheToken.get("access_token");??
  • ????GooglePlayBuyEntity?buyEntity?=?null;??
  • ????try?{??
  • ????????/**這是寫這篇博客時間時的最新API,v2版本。?
  • ?????????*?https://www.googleapis.com/androidpublisher/v2/applications/{packageName}?
  • ?????????*?/purchases/products/{productId}/tokens/{purchaseToken}?access_token={access_token}?
  • ?????????*/??
  • ????????String?url?=?"https://www.googleapis.com/androidpublisher/v2/applications";??
  • ????????StringBuffer?getURL?=?new?StringBuffer();??
  • ????????getURL.append(url);??
  • ????????getURL.append("/"?+?packageName);??
  • ????????getURL.append("/purchases/products");??
  • ????????getURL.append("/"?+?productId???);??
  • ????????getURL.append("/tokens/"?+?purchaseToken);??
  • ????????getURL.append("?access_token="?+?access_token);??
  • ????????URL?urlObtainOrder?=?new?URL(getURL.toString());??
  • ????????HttpURLConnection?connectionObtainOrder?=?(HttpURLConnection)?urlObtainOrder.openConnection();??
  • ????????connectionObtainOrder.setRequestMethod("GET");??
  • ????????connectionObtainOrder.setDoOutput(true);??
  • ????????//?如果認證成功??
  • ????????if?(connectionObtainOrder.getResponseCode()?==?HttpURLConnection.HTTP_OK)?{??
  • ????????????StringBuilder?sbLines?=?new?StringBuilder("");??
  • ????????????BufferedReader?reader?=?new?BufferedReader(new?InputStreamReader(??
  • ????????????????????connectionObtainOrder.getInputStream(),?"utf-8"));??
  • ????????????String?strLine?=?"";??
  • ????????????while?((strLine?=?reader.readLine())?!=?null)?{??
  • ????????????????sbLines.append(strLine);??
  • ????????????}??
  • ????????????//?把上面取回來的資料,放進JSONObject中,以方便我們直接存取到想要的參數??
  • ????????????JSONObject?jo?=?JSONObject.fromObject(sbLines.toString());??
  • ????????????Integer?status?=?jo.getInt("purchaseState");??
  • ????????????if(status?==?0){?//驗證成功??
  • ????????????????buyEntity?=?new?GooglePlayBuyEntity();??
  • ????????????????buyEntity.setConsumptionState(jo.getInt("consumptionState"));??
  • ????????????????buyEntity.setDeveloperPayload(jo.getString("developerPayload"));??
  • ????????????????buyEntity.setKind(jo.getString("kind"));??
  • ????????????????buyEntity.setPurchaseState(status);??
  • ????????????????buyEntity.setPurchaseTimeMillis(jo.getLong("purchaseTimeMillis"));??
  • ????????????}else{??
  • ????????????????//?購買無效??
  • ????????????????buyEntity?=?new?GooglePlayBuyEntity();??
  • ????????????????buyEntity.setPurchaseState(status);??
  • ????????????????logger.info("從GooglePlay賬單校驗失敗,原因是purchaseStatus為"?+?status);??
  • ????????????}??
  • ????????}?????
  • ????}?catch?(Exception?e)?{??
  • ????????e.printStackTrace();??
  • ????????buyEntity?=?new?GooglePlayBuyEntity();??
  • ????????buyEntity.setPurchaseState(-1);??
  • ????}??
  • ????return?buyEntity;??
  • }??
  • ? ? ? ??

    ? ? ? ? 到這里就寫完了,如果有什么疑問可以留言。

    ? ? ? ??另外,iOS應用內支付,蘋果商店AppStore購買信息校驗的博客在這里:http://blog.csdn.net/hjun01/article/details/44039939

    ?

    總結

    以上是生活随笔為你收集整理的【实例图文详解】OAuth 2.0 for Web Server Applications的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 免费禁漫天堂a3d | 色啪综合 | 看片免费黄在线观看入口 | www.黄色一片 | 看91| 国产欧美日韩久久 | 久久人妻少妇嫩草av无码专区 | 亚洲欧洲精品成人久久奇米网 | 国产精品自拍视频一区 | 综合xx网| 亚洲欧美成人 | 在线色资源 | 亚洲乱码国产乱码精品精 | 欧美色图11p | 美女脱了裤子让男人捅 | 久久激情网 | 久久99在线 | 日韩精品一区二区三区在线视频 | 日本夜夜操 | 欧美精品久久久久久久自慰 | 97欧美 | 熟妇高潮一区二区高潮 | 免费无遮挡网站 | 久操久热 | 亚洲天堂成人av | 老子影院午夜精品无码 | 在线观看av不卡 | 亚洲一区二区三区免费在线观看 | 夫妻性生活黄色大片 | 国产精品白嫩极品美女视频 | 亚洲春色在线 | av免费影院 | 天堂伊人网 | 一区二区在线视频观看 | 拔插拔插华人 | 日韩不卡| 精品久久久久久久久久久久 | 在线97视频| 嫩草视频网站 | 欧美日韩国产黄色 | 欧美性色19p| 丝袜黄色片 | 熟女精品一区二区三区 | 一级黄色网| 中文字幕一区二区人妻在线不卡 | 日本在线观看网站 | 欧美日韩在线高清 | 一区二区三区波多野结衣 | 午夜影视在线观看 | 国产一区第一页 | 免费看裸体视频网站 | 长腿校花无力呻吟娇喘的视频 | 国产精品丝袜视频 | 懂色av色吟av夜夜嗨 | 黑丝久久| 内地毛片| 亚洲成人自拍网 | 国产精品18久久久 | 黑人玩弄人妻一区二区三区影院 | 欧美野外猛男的大粗鳮 | 黑人一级视频 | 网爆门在线 | 国产精品久久久久久久久久免费 | 亚洲一区二区三 | 末发成年娇小性xxxxx | 人人妻人人澡人人爽人人欧美一区 | 西西4444www大胆无视频 | 成人午夜淫片100集 伊人久久国产 | 四虎国产精品永久在线国在线 | 欧美日韩精品网站 | 四虎影视在线 | 99人妻少妇精品视频一区 | 国产精品自拍小视频 | 91香蕉国产在线观看 | 国产视频播放 | 最近中文字幕在线观看视频 | 国产精品69久久久久 | 亚洲国产伊人 | 偷拍老头老太高潮抽搐 | 中文免费在线观看 | 日本欧美不卡 | 毛片大全在线观看 | 国产精品一区二区三区免费观看 | 少妇大叫太粗太大爽一区二区 | 亚洲精品一区二三区 | 丁香激情五月 | 一区二区三区四区五区av | 麻豆网站免费看 | 亚洲激情视频网站 | 懂色av一区二区三区免费观看 | 亚洲综合少妇 | 久久精品h | 日本高清视频www夜色资源 | 成人性生活免费视频 | 欧洲成人一区二区三区 | 精品麻豆视频 | 一级二级av| 亚洲精品在线不卡 | 欧美视频一二区 |