我正在尝试将 Google 跟踪代码管理器集成到我的项目中。在官方文档中,Google 建议使用 oauth2client 库。不幸的是,这个库已被弃用。我使用了 google_auth_oauthlib。我可以获取令牌并使用此令牌向 Google 跟踪代码管理器 API 发送请求。但我不决定如何在 Django 中存储凭据对象。在 oauth2client lib 中,有用于模型的 CredentialsField。我们可以使用 DjangoORMStorage 在此字段中存储 Credentials 对象。但我无法使用这个已弃用的库。还有其他方法吗?
Google 跟踪代码管理器文档位于 此处
我的代码在这里:
from google_auth_oauthlib.flow import Flow
from googleapiclient.discovery import build
FLOW = Flow.from_client_secrets_file(
settings.GOOGLE_OAUTH2_CLIENT_SECRETS_JSON,
scopes=[settings.GOOGLE_OAUTH2_SCOPE])
class GTMAuthenticateView(APIView):
def get(self,request,**kwargs):
FLOW.redirect_uri = settings.GOOGLE_OAUTH2_REDIRECT_URI
authorization_url, state = FLOW.authorization_url(access_type='offline',
include_granted_scopes='true')
return Response({'authorization_url':authorization_url,'state':state})
def post(self, request, **kwargs):
FLOW.fetch_token(code=request.data['code'])
credentials = FLOW.credentials
return Response({'token':credentials.token})
class GTMContainerView(APIView):
def get(self,request,**kwargs):
service = get_service()
containers = self.get_containers(service)
return Response({'containers':str(containers),'credentials':str(FLOW.credentials)})
@staticmethod
def get_containers(service):
account_list = service.accounts().list().execute()
container_list = []
for account in account_list['account']:
containers = service.accounts().containers().list(parent=account["path"]).execute()
for container in containers["container"]:
container["usageContext"] = container["usageContext"][0].replace("['", "").replace("']", "")
container_list.append(container)
return container_list
def get_service():
try:
credentials = FLOW.credentials
service = build('tagmanager', 'v2', credentials=credentials)
return service
except Exception as ex:
print(ex)
我已经研究这个主题有一段时间了,但似乎没有任何现成的解决方案(除了旧的 oauth2client lib 中提供的解决方案)。几乎所有在线可用的文档都依赖于将凭据存储在磁盘存储上,这是我根本不喜欢的方法。所以基本上我最终创建了自己的模型,用于存储凭证对象中的相关信息,并使用一些辅助类方法来快速存储和从数据库中检索凭证。
我包含了相关代码,以防万一有人发现它有用。我用它来与 youtube api 交互,但授权部分没有注意到这一点:
#models.py
class GoogleCredential(models.Model):
#In my case, I don't find necessary to store scopes in the DB
#even though they are required information in the credentials object
#So I just save it as a static var and inject it in the object
#during the retrieval
SCOPES = ["https://www.googleapis.com/auth/youtube", ]
token = models.CharField(null=False)
refresh_token = models.CharField(null=False)
token_uri = models.CharField(null=False)
client_id = models.CharField(null=False)
client_secret = models.CharField(null=False)
user = models.OneToOneField(User, null=False, on_delete=models.CASCADE)
@classmethod
def store_credentials(cls, credentials, user):
credentials = GoogleCredential.objects.get_or_create(user=user)[0]
credentials.token = credentials.token
credentials.refresh_token = credentials.refresh_token
credentials.token_uri = credentials.token_uri
credentials.client_id = credentials.client_id
credentials.client_secret = credentials.client_secret
credentials.user = user
credentials.save()
return credentials
@classmethod
def get_credentials(cls, user):
try:
user_credentials = GoogleCredential.objects.get(user=user)
credentials = Credentials(
token=user_credentials.token,
refresh_token=user_credentials.refresh_token,
token_uri=user_credentials.token_uri,
client_id=user_credentials.client_id,
client_secret=user_credentials.client_secret,
scopes=GoogleCredential.SCOPES
)
except Exception as ex:
credentials = None
return credentials
存储凭据的示例视图:
class YourAuthCallbackView(View):
def get(self, request, *args, **kwargs):
flow = Flow.from_client_secrets_file(
get_secrets_file_path(),
scopes=GoogleCredential.SCOPES,
redirect_uri=request.build_absolute_uri('..')
)
path = request.get_full_path()
flow.fetch_token(
authorization_response=request.build_absolute_uri(path)
)
GoogleCredential.store_credentials(
flow.credentials,
request.user
)
return redirect('/whatever')
在 api 请求中使用凭据的示例视图:
class YoutubeGetProfile(View):
def get(self, request, *args, **kwargs):
credentials = GoogleCredential.get_credentials(request.user)
if credentials is not None:
flow = Flow.from_client_secrets_file(
get_secrets_file_path(),
scopes=GoogleCredential.SCOPES,
redirect_uri=request.build_absolute_uri('...')
)
youtube_api = build('youtube', 'v3', credentials=credentials)
request = youtube_api.channels().list(part='snippet,contentDetails,statistics', mine=True)
response = request.execute()
#...
return redirect('/whatever')
只需切换到 Django 2 pip 安装 Django==2.2.12 我做到了并且效果很好