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