如何使用gmail进行一次身份验证并使用生成的令牌?

时间:2017-05-04 17:56:32

标签: python authentication oauth-2.0 gmail-api google-python-api

from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run_flow
from oauth2client.file import Storage
import requests    

CLIENT_ID = '9453asfasfaksdfh860b1osoiveogstt.apps.googleusercontent.com'
CLIENT_SECRET = '6gRid8wF7TW8asdfasdftX'


flow = OAuth2WebServerFlow(client_id=CLIENT_ID,
                           client_secret=CLIENT_SECRET,
                           scope='https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/admin.directory.user.readonly',
                           redirect_uri='http://example.com/auth_return')

storage = Storage('creds.data') #token details stored here
credentials = run_flow(flow, storage)
tokenhere=credentials.access_token #tokens generated

#send get request with token generated using requests
r=requests.get("https://www.googleapis.com/admin/directory/v1/users?domain=mydomain.ocm",headers={'Authorization': 'Bearer {token}'.format(token=tokenhere)})     
result=r.json()

这就是我成功通过Google验证并获取用户的方式。

现在我跑这个。它显示了选择要验证的Google帐户和同意屏幕以获取权限的页面。

但问题是每次运行时都会发生这种情况。

我知道,一旦我们授权下次我们不必一次又一次地遵循这些步骤,而是直接传递令牌或使用已保存的令牌。

这是如何真正实现的。没有确切的线索。有人请指导我。如何以及在哪里做这部分。现在我已成功验证并获得授权令牌。

EXTRA:我获取令牌的方式可能看起来不同,因为我试图直接在控制台中获取令牌,因此为此目的使用了一个模块,因此看起来如此

1 个答案:

答案 0 :(得分:0)

如果我理解正确,这应该是你想要的:

from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run_flow
from oauth2client.file import Storage
import requests
import os


CLIENT_ID = '9453asfasfaksdfh860b1osoiveogstt.apps.googleusercontent.com'
CLIENT_SECRET = '6gRid8wF7TW8asdfasdftX'

def get_new_token():
    flow = OAuth2WebServerFlow(client_id=CLIENT_ID,
                               client_secret=CLIENT_SECRET,
                               scope='https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/admin.directory.user.readonly',
                               redirect_uri='http://example.com/auth_return')
    storage = Storage('creds.data') #token details stored here
    credentials = run_flow(flow, storage)
    tokenhere=credentials.access_token #tokens generated
    return tokenhere

def retrieve_saved_token():
    if os.path.exists('creds.data'):
        with open('creds.data') as creds:
            tokenhere = creds.read()  # Change to reflect how the token data is reflected in your 'creds.data' file
    return tokenhere

def request_page(tokenhere):
    r = requests.get("https://www.googleapis.com/admin/directory/v1/users?domain=mydomain.com",
                     headers={'Authorization': 'Bearer {token}'.format(token=tokenhere)})
    result = r.json()

try:
    tokenhere = retrieve_saved_token()
    request_page(tokenhere)
except:
    tokenhere = get_new_token()
    request_page(tokenhere)

这里分解了所做的所有内容

为了更加面向对象,我将你的逻辑转化为函数:

def get_new_token():
    flow = OAuth2WebServerFlow(client_id=CLIENT_ID,
                               client_secret=CLIENT_SECRET,
                               scope='https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/admin.directory.user.readonly',
                               redirect_uri='http://example.com/auth_return')
    storage = Storage('creds.data') #token details stored here
    credentials = run_flow(flow, storage)
    tokenhere=credentials.access_token #tokens generated
    return tokenhere

def request_page(tokenhere):
    r = requests.get("https://www.googleapis.com/admin/directory/v1/users?domain=mydomain.com",
                     headers={'Authorization': 'Bearer {token}'.format(token=tokenhere)})
    result = r.json()

如果令牌文件存在,我还添加了一个新函数来检索已保存的令牌:

def retrieve_saved_token():
    if os.path.exists('creds.data'):
        with open('creds.data') as creds:
            tokenhere = creds.read()  # Change to reflect how the token data is reflected in your 'creds.data' file
    return tokenhere

最后,我们到达逻辑实际运行的部分。

首先它尝试从文件中检索令牌,如果该文件不存在则会引发异常,您将进入异常逻辑。 如果成功检索令牌,那么写入try逻辑的方式也会捕获,但如果该令牌已过期,则请求逻辑应该引发异常。

在异常逻辑中,它执行获取新令牌并使用该令牌请求页面的原始逻辑

try:
    tokenhere = retrieve_saved_token()
    request_page(tokenhere)
except:
    tokenhere = get_new_token()
    request_page(tokenhere)

编辑1

我假设你不仅要求页面而且还要操纵页面上的数据。要做到这一点,你将有另一个函数,通过在你创建的json对象'result'中查找标记来从页面中提取数据。我在下面的代码中将此函数称为“do_something_with_request_function()”。

第一个Try / Except将检查一个令牌文件是否存在,如果它存在则抓取该令牌并使用它,如果不存在则会生成一个新令牌。

第二次尝试除了有可能传入过期的令牌。因此,我们假设两种情况 场景1:传入有效令牌,您将获得请求中所需的页面。您用于解析页面上数据的方法将查找该页面上存在的特定字段,一切正常 场景2:您传递了无效令牌,您将获得过期/无效令牌的错误页面。如果找不到通常存在于您尝试访问的实际页面上的值,那么将该页面解析为json并尝试操作数据的方法会抛出错误。这会强制代码跳转到except块 except块生成一个新令牌,将其传递给再次请求页面并正确处理您的数据。

try:
    tokenhere = retrieve_saved_token()
except:
    tokenhere = get_new_token()
try:
    request_page(tokenhere)
    do_something_with_request_function(result)
except:
    tokenhere = get_new_token()
    request_page(tokenhere)
    do_something_with_request_function(result)