3

我已经看过关于此主题的其他问题,它似乎不符合我的错误。运行Google Sheets APIv4时,我得到的错误:上线service.spreadsheets().values().get(spreadsheetId=key, range=ranges).execute()HttpAccessTokenRefreshError:invalid_grant ...一小时限制刷新令牌

此错误只是偶尔弹出发生

raise HttpAccessTokenRefreshError(error_msg, status=resp.status) HttpAccessTokenRefreshError: invalid_grant

错误。如果我什么都不做,只需再次运行代码。这将再次带我通过认证流程的过程,我也得到

Authentication successful. Storing credentials to C:\Users\jason\.credentials\sheets.googleapis.com-python-quickstart.json

在这之后,我可以到同HttpAccessTokenRefreshError: invalid_grant再次弹出运行了一段时间的任何代码,我不得不再次重新验证。

我该如何预防?

我使用的代码是developers.google.com/sheets/api/quickstart/python。

我试着使用ntp同步的时间与以下

import time 
import os 
try: 
    import ntplib 
    client = ntplib.NTPClient() 
    response = client.request('pool.ntp.org') 
    os.system('date ' + time.strftime('%m%d%H%M%Y.%S',time.localtime(response.tx_time))) 
except: 
    print('Could not sync with time server.') 

print('Done.') 

但得到:我输入当前日期后

The system cannot accept the date entered. 
Enter the new data: (mm-dd-yy) 

,什么都不会发生。

我也查看了此页。 https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35#.5utz2vcn6

当我运行超过1小时的代码完成代码时,也会出现此问题。在刷新令牌上。它总是炸弹。

现在我在想,授予的令牌只能持续一个小时并刷新,它总是炸弹。

我已经发布的代码,用于连接:

class APIv4: 
    def __init__(self): 
    credentials = get_credentials() 
    http = credentials.authorize(httplib2.Http()) 
    discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?' 
        'version=v4') 
    self.service = discovery.build('sheets', 'v4', http=http, 
           discoveryServiceUrl=discoveryUrl) 

def get_credentials(): 
    """Gets valid user credentials from storage. 

    If nothing has been stored, or if the stored credentials are invalid, 
    the OAuth2 flow is completed to obtain the new credentials. 

    Returns: 
     Credentials, the obtained credential. 
    """ 
    home_dir = os.path.expanduser('~') 
    credential_dir = os.path.join(home_dir, '.credentials') 
    if not os.path.exists(credential_dir): 
     os.makedirs(credential_dir) 
    credential_path = os.path.join(credential_dir, 
            'sheets.googleapis.com-python-quickstart.json') 

    store = Storage(credential_path) 
    credentials = store.get() 
    if not credentials or credentials.invalid: 
     flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) 
     flow.user_agent = APPLICATION_NAME 
     if flags: 
      credentials = tools.run_flow(flow, store, flags) 
     else: # Needed only for compatibility with Python 2.6 
      credentials = tools.run(flow, store) 
     print('Storing credentials to ' + credential_path) 
    return credentials 
+0

如果您在使用OAuth时遇到问题,请尝试使用API​​密钥,因为此OAuth都是[受支持的API凭证类型](https://developers.google.com/sheets/api/guides/authorizing#APIKey )。在获得API密钥后,应用程序可以将查询参数'key = yourAPIKey'附加到所有请求URL。 –

+0

@Rebot先生您可以给我一些关于如何设置的示例代码吗?我不明白服务构建以及它如何与Google表APIv4一起使用。我跟随您的链接从凭据中获取我的控制台中的API密钥。我不确定这是否适用于我,因为我的数据不公开。它表示它不访问任何私人用户数据。 – jason

+0

@ Mr.Rebot“尝试使用API​​密钥,因为这和OAuth都是由Sheets API支持的凭证类型。”是不正确的。只有电子表格是公开的,API密钥才会有效。 – pinoyyid

回答

1

作为一般的想法,似乎是与你的访问令牌的调用之间的刷新问题。

,要么意味着一些您的凭据都没有正确传递或有一些问题,你的本地计算机的时间(虽然比第一选择似乎不太可能)

我建议研究在这个问题上规定的可能性: https://github.com/google/oauth2client/issues/451

  1. (不太可能)你为什么不试图迫使时钟更新用ntpdate。安装NTP,并给它一个尝试,因为用户指出,为他工作
  2. Ok. After a loong research I guess I found out the problem. In fact, refresh_token was missing from the user credential, but the issue was tricky.

    The refresh token is given for the FIRST time when the application asks the user for permissions. The refresh token is given ONLY IF the flow's step 1 includes the parameters approval_prompt="force"

    For some reason the user (me) hadn't got refresh_token in user's credentials, so I revoked permissions from the application on My Account -> Security -> Applications, and restarted the OAuth dance again. Now I got refresh_token.

更新#2选项:

在此之后guide和推荐上述,笔者认为,必须添加到这个代码段(直接从导向截取):

# Create a state token to prevent request forgery. 
# Store it in the session for later validation. 
state = hashlib.sha256(os.urandom(1024)).hexdigest() 
session['state'] = state 
# Set the client ID, token state, and application name in the HTML while 
# serving it. 
response = make_response(
    render_template('index.html', 
        CLIENT_ID=CLIENT_ID, 
        STATE=state, 
        APPLICATION_NAME=APPLICATION_NAME)) 

prompt=consent的线,然后执行吨他是上述引用响应的第三步(选项2)。

另一种选择是使用approval_prompt=force但您必须在两者之间进行选择,因为它们不能很好地协同工作。

祝你好运:)

+0

你能把#2分成几步,并且更清楚,我不明白。 – jason

+0

@jason我编辑了我的答案,希望它有助于 –

+0

是的。 HTTP://计算器。COM /问题/ 10827920 /不接收谷歌-的OAuth刷新令牌/ 10857806#10857806。这是我的答案。我加了'offline'和'force'属性。现在运行了一个小时。 – jason

1

的几点思考....

您发布的timekit.io博客链接是通过替代运行相当不错。在你的情况下,它听起来不像时间相关,ntp是矫枉过正的。只要你的时间或多或少是最新的,你会没事的。

您的代码运行,然后在“无效授权”一小时后失败。这意味着某些东西试图使用刷新令牌来生成新的访问令牌并失败。如果您正在进行自己的刷新,显然请检查您是否正确检索并使用刷新令牌。我的猜测是你依靠谷歌python库来做到这一点(呃,我讨厌图书馆哈哈)。

所以,对我来说最可能的原因是: -

  1. 刷新令牌没有被正确保存和恢复使用的刷新
  2. 刷新令牌是陈旧的(即超过。 25刷新令牌旧)。如果您在开发过程中运行重复测试,就会发生这种情况务必确保您使用的是最新的RT。
  3. 刷新令牌为空,因为它仅在用户第一次授权您的应用程序时提供。尝试进入https://myaccount.google.com/permissions?pli=1并删除您的应用的权限,然后重新开始。

如果您可以捕获http跟踪,它将有助于调试。看看python库是否有任何可以打开的调试/日志功能(我知道Java库的功能)。

+0

我已经发布了代码进行身份验证。请看一下。我基本上使用谷歌网站上的启动指南中的代码。 – jason

+0

不幸的是,我从来没有使用(也不会)谷歌python库,所以我无法帮助读取代码。我建议在使用凭证之前立即确认Refresh Token看起来有效。也尝试我的项目3,即。删除权限并重试。 – pinoyyid