針對網(wǎng)絡服務器應用使用 OAuth 2.0
https://developers.google.com/identity/protocols/oauth2/web-server?hl=zh-cn#offline
本文檔介紹了 Web 服務器應用如何使用 Google API 客戶端庫或 Google OAuth 2.0 端點來實現(xiàn) OAuth 2.0 授權以訪問 Google API。
OAuth 2.0 可讓用戶與應用共享特定數(shù)據(jù)毒坛,同時保持用戶名失暂、密碼和其他信息的私密性桨菜。例如稽物,應用可以使用 OAuth 2.0 向用戶請求在其 Google 云端硬盤中存儲文件的權限鸳惯。
此 OAuth 2.0 流程專門用于用戶授權识腿。它專為可以存儲機密信息并維護狀態(tài)的應用而設計出革。適當授權的網(wǎng)絡服務器應用可以在用戶與應用互動時或用戶離開應用后訪問 API。
Web 服務器應用通常還會使用服務帳號向 API 請求授權渡讼,尤其是在調(diào)用 Cloud API 來訪問基于項目的數(shù)據(jù)時骂束,而不是訪問特定于用戶的數(shù)據(jù)時。網(wǎng)絡服務器應用可以將服務帳號與用戶授權結合使用成箫。
注意:考慮到正確實現(xiàn)的安全性影響展箱,我們強烈建議您在與 Google 的 OAuth 2.0 端點互動時使用 OAuth 2.0 庫。使用他人提供的經(jīng)過充分調(diào)試的代碼是最佳做法蹬昌,有助于保護您自己和用戶混驰。如需了解詳情,請參閱客戶端庫凳厢。
客戶端庫
本頁面上特定于語言的示例使用 Google API 客戶端庫來實現(xiàn) OAuth 2.0 授權账胧。要運行代碼示例,您必須先安裝適用于您的語言的客戶端庫先紫。
當您使用 Google API 客戶端庫處理應用的 OAuth 2.0 流程時治泥,客戶端庫會執(zhí)行應用需要自行處理的許多操作。例如遮精,它會決定應用何時可以使用或刷新存儲的訪問令牌居夹,以及應用何時必須重新征得用戶同意败潦。客戶端庫還會生成正確的重定向網(wǎng)址准脂,并有助于實現(xiàn)使用授權代碼交換訪問令牌的重定向處理程序劫扒。
適用于服務器端應用的 Google API 客戶端庫支持以下語言:
前提條件
為您的項目啟用 API
任何調(diào)用 Google API 的應用都需要在 API Console中啟用這些 API。
如需為您的項目啟用該 API狸膏,請按以下步驟操作:
- Open the API Library (在 Google API Console中)沟饥。
- If prompted, select a project, or create a new one.
- API Library 列出了所有可用的 API,按產(chǎn)品系列和熱門程度分組湾戳。如果列表中沒有顯示您要啟用的 API贤旷,請使用搜索功能查找該 API,或點擊該 API 所屬的產(chǎn)品系列中的查看全部砾脑。
- 選擇您要啟用的 API幼驶,然后點擊啟用按鈕。
- If prompted, enable billing.
- If prompted, read and accept the API's Terms of Service.
創(chuàng)建授權憑據(jù)
任何使用 OAuth 2.0 訪問 Google API 的應用都必須使用授權憑據(jù)向 Google 的 OAuth 2.0 服務器標識該應用韧衣。以下步驟說明了如何為項目創(chuàng)建憑據(jù)盅藻。然后,您的應用可以使用這些憑據(jù)訪問為該項目啟用的 API畅铭。
Go to the Credentials page.
依次點擊創(chuàng)建憑據(jù) > OAuth 客戶端 ID氏淑。
選擇 Web 應用應用類型。
-
填寫表單硕噩,然后點擊創(chuàng)建夸政。使用 PHP、Java榴徐、Python守问、Ruby 和 .NET 等語言和框架的應用必須指定經(jīng)授權的重定向 URI。重定向 URI 是 OAuth 2.0 服務器可將響應發(fā)送到的端點坑资。這些端點必須遵循 Google 的驗證規(guī)則耗帕。
如需進行測試,您可以指定引用本地機器的 URI袱贮,例如
http://localhost:8080
仿便。請注意這一點,請注意攒巍,本文檔中的所有示例均使用http://localhost:8080
作為重定向 URI嗽仪。我們建議您設計應用的身份驗證端點,使應用不會向頁面上的其他資源公開授權代碼柒莉。
創(chuàng)建憑據(jù)后闻坚,從 API Console下載 client_secret.json 文件。將文件安全地存儲在只有您的應用可以訪問的位置兢孝。
重要提示:請勿將 client_secret.json 文件存儲在可公開訪問的位置窿凤。此外仅偎,如果您與應用共享源代碼(例如,在 GitHub 上)雳殊,請將 client_secret.json 文件存儲在源代碼樹之外橘沥,以避免無意中共享您的客戶端憑據(jù)。
確定訪問權限范圍
通過范圍夯秃,您的應用可以僅請求訪問所需的資源座咆,同時還能控制用戶向您的應用授予的訪問量。因此仓洼,請求的范圍數(shù)與征得用戶同意的可能性之間可能存在逆向關系箫措。
在開始實現(xiàn) OAuth 2.0 授權之前,我們建議您確定應用需要訪問權限的范圍衬潦。
我們還建議您的應用通過增量授權流程請求對授權范圍的訪問權限,在此過程中植酥,您的應用會在上下文中請求訪問用戶數(shù)據(jù)镀岛。此最佳做法可幫助用戶更輕松地了解應用需要其請求的訪問權限的原因。
OAuth 2.0 API 范圍文檔包含可用于訪問 Google API 的完整范圍列表友驮。
如果您的公共應用使用了允許訪問特定用戶數(shù)據(jù)的范圍漂羊,則必須完成驗證流程。測試您的應用時卸留,如果您在屏幕上看到未經(jīng)驗證的應用走越,您必須提交驗證請求以將其移除。請詳細了解未經(jīng)驗證的應用耻瑟,并在幫助中心獲取有關應用驗證的常見問題解答旨指。
特定語言要求
要運行本文檔中的任何代碼示例,您需要擁有 Google 帳號喳整、互聯(lián)網(wǎng)訪問權限和網(wǎng)絡瀏覽器谆构。如果您使用的是某個 API 客戶端庫,另請參閱下文針對特定語言的要求框都。
獲取 OAuth 2.0 訪問令牌
以下步驟顯示了您的應用如何與 Google 的 OAuth 2.0 服務器進行交互搬素,以獲取用戶同意代表用戶執(zhí)行 API 請求。您的應用必須先獲得用戶同意魏保,然后才能執(zhí)行需要用戶授權的 Google API 請求熬尺。
下面的列表快速總結了這些步驟:
您的應用確定所需的權限。
您的應用會將用戶連同請求的權限列表一起重定向到 Google谓罗。
用戶決定是否向您的應用授予權限粱哼。
您的應用會查找用戶的決定。
如果用戶被授予所請求的權限檩咱,您的應用將檢索代表用戶發(fā)出 API 請求所需的令牌皂吮。
第 1 步:設置授權參數(shù)
第一步是創(chuàng)建授權請求戒傻。該請求會設置用于標識您的應用的參數(shù),并定義用戶將向您的應用授予的權限蜂筹。
如果您使用 Google 客戶端庫進行 OAuth 2.0 身份驗證和授權需纳,則需要創(chuàng)建并配置用于定義這些參數(shù)的對象。
如果您直接調(diào)用 Google OAuth 2.0 端點艺挪,系統(tǒng)會生成一個網(wǎng)址并針對該網(wǎng)址設置參數(shù)不翩。
以下標簽定義了網(wǎng)絡服務器應用支持的授權參數(shù)。各種語言的示例還展示了如何使用客戶端庫或授權庫來配置可設置這些參數(shù)的對象麻裳。
第 2 步:重定向到 Google 的 OAuth 2.0 服務器
將用戶重定向到 Google 的 OAuth 2.0 服務器口蝠,以啟動身份驗證和授權流程。這通常發(fā)生在您的應用首次需要訪問用戶數(shù)據(jù)時津坑。對于增量授權妙蔗,當您的應用首次需要訪問其尚未有權訪問的其他資源時,也會執(zhí)行此步驟疆瑰。
Google 的 OAuth 2.0 服務器對用戶進行身份驗證眉反,并在征得用戶同意后允許您的應用訪問所請求的范圍。系統(tǒng)會使用您指定的重定向網(wǎng)址將響應發(fā)送回您的應用穆役。
第 3 步:Google 提示用戶同意
在此步驟中寸五,用戶可以決定是否向應用請求訪問權限。在此階段耿币,Google 會顯示一個意見征求窗口梳杏,其中會顯示應用的名稱以及使用用戶的授權憑據(jù)請求訪問權限的 Google API 服務以及要授予的訪問權限范圍的摘要。然后淹接,用戶可以同意向您的應用所請求的一個或多個范圍授予訪問權限十性,或拒絕該請求。
在此階段塑悼,您的應用會等待 Google 的 OAuth 2.0 服務器響應(表明是否授予了任何訪問權限)烁试,因此在此階段無需執(zhí)行任何操作。下一步中說明了該響應拢肆。
第 4 步:處理 OAuth 2.0 服務器響應
OAuth 2.0 服務器使用請求中指定的網(wǎng)址響應您應用的訪問請求减响。
如果用戶批準了該訪問請求,響應中將包含授權代碼郭怪。如果用戶未批準該請求支示,則響應中會包含錯誤消息。返回網(wǎng)絡服務器的授權代碼或錯誤消息會顯示在查詢字符串上鄙才,如下所示:
第 5 步:使用授權代碼交換刷新令牌和訪問令牌
網(wǎng)絡服務器收到授權代碼后颂鸿,可以使用授權代碼換取訪問令牌。
調(diào)用 Google API
重定向 URI 驗證規(guī)則
Google 會應用以下驗證規(guī)則來重定向 URI攒庵,以幫助開發(fā)者確保其應用安全無虞嘴纺。您的重定向 URI 必須遵守這些規(guī)則败晴。如需了解網(wǎng)域、主機栽渴、路徑尖坤、查詢、架構和用戶信息的定義闲擦,請參閱 RFC 3986 第 3 節(jié)慢味。
增量授權
在 OAuth 2.0 協(xié)議中,您的應用會請求訪問由范圍標識的資源墅冷。這被認為是一種最佳的用戶體驗做法纯路,即在您需要時對資源進行授權。為了啟用這種做法寞忿,Google 的授權服務器支持增量授權驰唬。此功能可讓您根據(jù)需要請求范圍,如果用戶為新范圍授予權限腔彰,則會返回授權代碼叫编,該代碼可能會交換包含用戶向項目授予的所有范圍的令牌。
例如萍桌,如果應用支持用戶試聽曲目和創(chuàng)建合輯,在登錄時可能需要的資源可能很少凌简,可能只有登錄用戶的名字上炎。但是,保存已完成的合輯需要訪問其 Google 云端硬盤雏搂。多數(shù)人會在應用確實需要的時候訪問他們的 Google 云端硬盤藕施,自然會發(fā)現(xiàn)應用很自然。
在這種情況下凸郑,在登錄時裳食,應用可能會請求 openid
和 profile
范圍來執(zhí)行基本登錄,然后在第一次請求保存組合時請求 https://www.googleapis.com/auth/drive.file
范圍芙沥。
要實現(xiàn)增量授權诲祸,您需要完成請求訪問令牌的常規(guī)流程,但請確保授權請求包含之前授予的范圍而昨。這種方法可讓您的應用不必管理多個訪問令牌救氯。
以下規(guī)則適用于通過增量授權獲得的訪問令牌:
- 此令牌可用于訪問與新合并的授權中任何一個范圍對應的資源。
- 當您使用合并授權的刷新令牌獲取訪問令牌時歌憨,訪問令牌代表合并授權着憨,可用于響應中包含的任何
scope
值。 - 合并授權包含用戶向 API 項目授予的所有范圍务嫡,即使授權來自不同的客戶端也是如此甲抖。例如漆改,如果用戶使用應用的桌面客戶端授予對一個范圍的訪問權限,然后通過移動客戶端向同一應用授予另一個范圍的訪問權限准谚,則合并授權將同時包括這兩個范圍挫剑。
- 如果您撤消代表合并授權的令牌,則代表關聯(lián)用戶同時撤消該授權范圍的所有訪問權限氛魁。
注意:如果選擇包含已獲授權的范圍暮顺,系統(tǒng)會自動將用戶之前授予的范圍添加到您的授權請求。如果您的應用當前未獲準請求在響應中返回的所有范圍秀存,則系統(tǒng)可能會顯示警告或錯誤頁面捶码。如需了解詳情,請參閱未經(jīng)驗證的應用或链。
第 1 步:設置授權參數(shù)中特定于語言的代碼示例以及第 2 步:重定向至 Google 的 OAuth 2.0 服務器中的示例 HTTP/REST 重定向網(wǎng)址均使用增量授權惫恼。下面的代碼示例還顯示了您需要添加才能使用增量授權的代碼。
刷新訪問令牌(離線訪問)
訪問令牌會定期過期澳盐,并成為相關 API 請求的無效憑據(jù)祈纯。如果您請求離線訪問與此令牌相關聯(lián)的范圍,則可以刷新訪問令牌叼耙,而無需提示用戶授予權限(包括用戶不存在時)腕窥。
- 如果您使用 Google API 客戶端庫,則客戶端對象會根據(jù)需要刷新訪問令牌筛婉,前提是您將該對象配置為可離線訪問簇爆。
- 如果您未使用客戶端庫,則需要在將用戶重定向到 Google 的 OAuth 2.0 服務器時將
access_type
HTTP 查詢參數(shù)設為offline
爽撒。在這種情況下入蛆,當您用授權代碼交換訪問令牌時,Google 的授權服務器會返回刷新令牌硕勿。然后哨毁,如果訪問令牌過期(或其他任何時間),您可以使用刷新令牌來獲取新的訪問令牌源武。
對于需要在用戶不存在時訪問 Google API 的任何應用扼褪,請求離線訪問是必需的。例如粱栖,如果應用在預定時間執(zhí)行備份服務或執(zhí)行操作迎捺,那么在用戶不存在時必須能夠刷新其訪問令牌。默認訪問方式稱為 online
查排。
服務器端 Web 應用凳枝、已安裝的應用和設備均在授權過程中獲取刷新令牌。刷新令牌通常不用于客戶端 (JavaScript) Web 應用。
撤消令牌
在某些情況下岖瑰,用戶可能會想撤消授予某個應用的訪問權限叛买。用戶可以通過訪問帳號設置來撤消訪問權限。如需了解詳情蹋订,請參閱移除有權訪問您帳號的第三方網(wǎng)站和應用的網(wǎng)站或應用訪問權限部分率挣。
應用也能夠以編程方式撤消其訪問權限。在用戶退訂露戒、移除應用或應用所需的 API 資源發(fā)生了顯著變化的情況下椒功,程序化撤消非常重要。換言之智什,移除流程的一部分可能包括 API 請求动漾,以確保之前授予應用的權限被移除。
注意:成功撤消后荠锭,可能需要一些時間才能完全撤消旱眯。
完整示例
import json
import flask
import requests
app = flask.Flask(__name__)
CLIENT_ID = '123456789.apps.googleusercontent.com'
CLIENT_SECRET = 'abc123' # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly'
REDIRECT_URI = 'http://example.com/oauth2callback'
@app.route('/')
def index():
if 'credentials' not in flask.session:
return flask.redirect(flask.url_for('oauth2callback'))
credentials = json.loads(flask.session['credentials'])
if credentials['expires_in'] <= 0:
return flask.redirect(flask.url_for('oauth2callback'))
else:
headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
req_uri = 'https://www.googleapis.com/drive/v2/files'
r = requests.get(req_uri, headers=headers)
return r.text
@app.route('/oauth2callback')
def oauth2callback():
if 'code' not in flask.request.args:
auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code'
'&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE)
return flask.redirect(auth_uri)
else:
auth_code = flask.request.args.get('code')
data = {'code': auth_code,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'authorization_code'}
r = requests.post('https://oauth2.googleapis.com/token', data=data)
flask.session['credentials'] = r.text
return flask.redirect(flask.url_for('index'))
if __name__ == '__main__':
import uuid
app.secret_key = str(uuid.uuid4())
app.debug = False
app.run()
問題: 為什么先請求授權碼,然后用授權碼獲取訪問令牌证九。 為什么不直接返回訪問令牌删豺。