你確定懂OAuth 2.0的三方軟體和受保護資源服務?

公眾號-JavaEdge發表於2020-10-21

本文旨在闡明 OAuth2.0 體系中第三方軟體和受保護資源服務的職責。

1 構建第三方軟體應用

若基於公眾號開放平臺構建一個xx文章排版軟體的輕應用,需要先到公眾號開放平臺申請註冊成為開發者,再建立個應用就可以開始開發了。

1.1 開發過程的關鍵節點

1.1.1 註冊資訊

xx軟體必須先有身份,才能參與 OAuth 2.0 流程。即xx需要擁有 app_idapp_serect、自己的回撥地址 redirect_uri、申請許可權等資訊。
這稱為靜態註冊,即xx開發人員提前登入到公眾號開放平臺手動註冊,以便後續使用這些註冊的相關資訊來請求訪問令牌。

1.1.2 引導授權

當使用者要使用三方軟體操作在受保護資源上的資料,就需要三方軟體引導
授權。
大家也很熟悉,我要使用xx來對我公眾號裡的文章排版時,我首先訪問的
一定是xx軟體,而不是授權服務&受保護資源服務。

但xx需要我的授權,只有授權服務才能允許我的操作。所以xx需要將我引導至授權服務

String oauthUrl = "http://localhost:8081/Oauth?reqType=oauth"; response.sendRedirect(toOauthUrl);

讓使用者為三方軟體授權,得到授權後,三方軟體才可以代表使用者去訪問資料。即xx獲得授權後,就能代表我去排版文章。

1.1.3 使用訪問令牌

第三方軟體的最終目的:拿到令牌後去使用令牌。目前OAuth 2.0 令牌只支bearer 型別的令牌,即任意字串格式的令牌。

官方規範給出的使用訪問令牌請求的方式,有三種

Form-Encoded Body Parameter(表單引數)

URI Query Parameter(URI 查詢引數)

Authorization Request Header Field(授權請求頭部欄位)

如何選型?

  • OAuth 2.0 官方建議,系統在接入 OAuth 2.0 前資訊傳遞的請求載體是 JSON,若繼續採用表單引數提交,令牌就無法加入。
  • 若採用引數傳遞,URI 會被整體複製,安全性最差。
  • 請求頭部欄位無上述顧慮,因此被官方推薦。

但小小推薦採用表單提交 POST 方式提交令牌,類似如下程式碼所示。畢竟官方建議指的是在接入 OAuth 2.0 前,若你已採用 JSON 請求體條件下,才不建議使用表單提交。倘若一開始三方軟體和平臺都一致採用表單提交,就沒問題了。因為表單提交在保證安全傳輸同時,無需處理 Authorization 頭部資訊。

String protectedURl="http://localhost:8081/ProtectedServlet";
Map<String, String> paramsMap = new HashMap<String, String();
paramsMap.put("app_id","APPID_XX);
paramsMap.put("app_secret","APPSECRET_XX");
paramsMap.put("token",accessToken);

String result = HttpURLClient.doPost(protectedURl,HttpURLClient.mapToStr(paramsMap));

1.1.4 使用重新整理令牌

解決痛點

若訪問令牌過期了,xx總不能立馬提示讓我這客戶重新授權吧!

就需要重新整理令牌。重新整理令牌需注意何時決定使用重新整理令牌。

在xx排版軟體收到訪問令牌同時,也會收到訪問令牌的過期時間 expires_in。優秀的三方軟體應將 expires_in 值儲存並定時檢測;若發現 expires_in 即將過期,則需要利用 refresh_token 重新請求授權服務,獲取新的有效訪問令牌。
除定時檢測可提前發現訪問令牌是否快過期,還有“現場”發現。即比如xx訪問我的公眾號文章時,突然收到一個訪問令牌失效的響應,此時xx立即使用 refresh_token 請求一個訪問令牌,以便繼續代表我使用我的這些文章資料。

可得:

  • 定時檢測方案需開發定時任務
  • “現場”發現,就沒這額外工作咯

還是推薦定時檢測,因可以帶來“提前量”,以便讓更好掌握主動權。

重新整理令牌是一次性的,使用後就失效,但它的有效期會比訪問令牌長。
若重新整理令牌也過期呢?
需將重新整理令牌和訪問令牌都放棄,幾乎回到系統初始狀態,只能讓使用者重授權。

1.2 服務市場

  • 什麼是服務市場?

    三方開發者開發的軟體,都發布到這樣一個“市場”裡售賣。

2 構建受保護資源服務

受保護資源最終指向 API,比如排版軟體中的受保護資源就是文章查詢 API、批量查詢 API 等及公眾號頭像、暱稱的 API。
在網際網路上的系統之間的通訊,基本都是以 Web API 為載體的形式進行。授權服務最終保護的就是這些 API。在構建受保護資源服務時,除檢查令牌的合法性,更關鍵是許可權範圍。校驗許可權的佔比大。肯定要看該令牌到底能操作哪些、能訪問那些資料。

2.1 不同許可權對應不同操作

操作對應 API,比如公眾號平臺提供有查詢、新增、刪除文章 API。若xx請求過來的一個訪問令牌 access_token 的 scope 許可權範圍只對應查詢、新增 API,那包含該 access_token 值的請求,無法執行刪除文章 API。

2.2 不同許可權對應不同資料

資料,指某 API 裡包含的欄位資訊。比如,有一個查詢我的資訊的API,返回值包括 Contact(email、phone、qq)、Like(Basketball、Swimming)、Personal Data(sex、age、nickname)。若xx請求過來的一個訪問令牌 access_token 的 scope 許可權範圍只對應 Personal Data,那麼包含該 access_token 值的請求就不能獲取到 Contact 和 Like 的資訊。

這種許可權範圍的粒度要比“不同的許可權對應不同的操作”的粒度要小,遵循最小許可權範圍原則。

2.3 不同使用者對應不同資料

這種許可權實際上只是換了一種維度,將其定位到使用者。

一些基礎類資訊,比如獲取地理位置、天氣預報,不帶使用者歸屬屬性,即這些並不歸屬某使用者,是公有資訊。這樣資訊,平臺提供出去的 API 介面都是“中性”的,沒有使用者屬性。

但更多場景卻是基於使用者屬性。使用者每次推送文章,xx都要知道文章是哪個使用者的。使用者為xx授權,xx獲取的 access_token 實際上就包含公眾號使用者的這個使用者屬性。
公眾號開放平臺的受保護資源服務每次接收到xx的請求,都會根據該請求中
access_token 的值找到對應的使用者 ID,繼而根據使用者 ID 查詢到該使用者的文章,即不同使用者對應不同文章資料。

3 微服務架構下 API GATEWAY 的意義

現在已是分散式系統,若有很多受保護資源服務,比如提供使用者資訊查詢的使用者資源服務、提供文章查詢的文章資源服務、提供視訊查詢的視訊資源服務,那每個受保護資源服務豈不是都要把上述許可權範圍校驗執行一遍,不就有大量重複?
為解決這問題,應有統一閘道器層處理校驗,所有請求都會經過 跳轉到不同受保護資源服務。如此無需在每個受保護資源服務上都做許可權校驗,只在 API GATEWAY 做即可。

參考

  • 如何安全、快速地接入OAuth 2.0

相關文章