Joh*_*ohn 6 oauth google-api oauth-2.0 python-3.x google-oauth
我在这里使用 Google 的 python 快速启动脚本:https ://developers.google.com/calendar/quickstart/python
在正常情况下效果很好。我可以允许它访问我的 Gmail 帐户,并且它可以创建 Google 日历条目。
但是,如果我在浏览器中登录我的 Gmail 帐户,转到安全性,并撤销我的应用程序对我的 Google 帐户的访问权限,则快速启动脚本不会识别它。它只是崩溃了:
$ python quickstart.py
Getting the upcoming 10 events
Traceback (most recent call last):
File "quickstart.py", line 52, in <module>
main()
File "quickstart.py", line 42, in main
orderBy='startTime').execute()
File "/opt/my_project/venv3/lib/python3.6/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/opt/my_project/venv3/lib/python3.6/site-packages/googleapiclient/http.py", line 851, in execute
method=str(self.method), body=self.body, headers=self.headers)
File "/opt/my_project/venv3/lib/python3.6/site-packages/googleapiclient/http.py", line 165, in _retry_request
resp, content = http.request(uri, method, *args, **kwargs)
File "/opt/my_project/venv3/lib/python3.6/site-packages/google_auth_httplib2.py", line 213, in request
self.credentials.refresh(self._request)
File "/opt/my_project/venv3/lib/python3.6/site-packages/google/oauth2/credentials.py", line 136, in refresh
self._client_secret))
File "/opt/my_project/venv3/lib/python3.6/site-packages/google/oauth2/_client.py", line 237, in refresh_grant
response_data = _token_endpoint_request(request, token_uri, body)
File "/opt/my_project/venv3/lib/python3.6/site-packages/google/oauth2/_client.py", line 111, in _token_endpoint_request
_handle_error_response(response_body)
File "/opt/my_project/venv3/lib/python3.6/site-packages/google/oauth2/_client.py", line 61, in _handle_error_response
error_details, response_body)
google.auth.exceptions.RefreshError: ('invalid_grant: Token has been expired or revoked.', '{\n "error": "invalid_grant",\n "error_description": "Token has been expired or revoked."\n}')
Run Code Online (Sandbox Code Playgroud)
如果我在引发异常的行之前添加一些调试行,我会看到以下内容:
creds.valid: True
creds.expired: False
Run Code Online (Sandbox Code Playgroud)
我知道我可以捕获 google.auth.exceptions.RefreshError。我遇到的问题是,quickstart.py 开头有一整段代码,其目的是检测令牌是否有效,但它似乎无法检测到这个相当简单的场景,并且直到我实际上尝试使用令牌来执行命令。将每个执行(或至少第一个)放在 try- except 块中,以防脚本的第一部分无法完成检测令牌被撤销的工作,这似乎很愚蠢。
有没有办法在我实际尝试使用证书之前检测到该证书已被吊销?为什么 creds.valid 和 creds.expired 不起作用?
更新:看起来如果您等待足够长的时间(几分钟或几小时 - 不确定),creds.valid 和 creds.expired 最终将显示凭据不再有效。然而,这一次,当凭据看起来有效但无法使用时,如果我没有正确处理它,就足以使我的程序崩溃。
更新2:我唯一能想到的就是运行类似的东西:
from googleapiclient.discovery import build
from google.auth.exceptions import RefreshError
...
try:
service = build('calendar', 'v3', credentials=creds)
service.events().list(calendarId='primary', maxResults=1).execute()
except RefreshError:
...
...
Run Code Online (Sandbox Code Playgroud)
就在检查凭据是否有效的代码之后。有点像最终检查。这可行,但看起来有点脏,因为它需要额外调用 Google API 服务器,并且基本上正是我上面所说的 - 将第一次执行放在 try- except 块中。难道就没有更好的办法了吗?
本快速入门适用于使用您自己的凭据的简单案例。他们显然不希望您撤销自己的授权。不是仅在凭证过期时才刷新凭证,而是在每次开始时刷新访问令牌。如果刷新令牌已被撤销,则第一次刷新将成为故障点。
# If there are no (valid) credentials available, let the user log in.
if creds and creds.refresh_token:
try:
creds.refresh(Request())
except RefreshError:
logger.error("Credentials could not be refreshed, possibly the authorization was revoked by the user.")
os.unlink('token.pickle')
return
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6440 次 |
| 最近记录: |