Вам не следует использовать Flow.run_local_server () , если у вас нет намерения развертывать код. Это потому, что run_local_server
запускает браузер на сервере для завершения потока.
Это прекрасно работает, если вы разрабатываете проект локально для себя.
Если вы намерены использование локального сервера для согласования потока OAuth. URI перенаправления, настроенный в ваших секретах, должен совпадать с этим, локальный сервер по умолчанию для хоста - localhost
, а порт - 8080
.
Если вы хотите развернуть код, вы должны выполнить поток через обмен между браузером пользователя, вашим сервером и Google.
Поскольку у вас уже запущен сервер Django , вы можете использовать это для согласования потока.
Например,
Допустим, в проекте Django есть приложение для твитов с модулем urls.py
, как показано ниже.
from django.urls import path, include
from . import views
urlpatterns = [
path('google_oauth', views.google_oath, name='google_oauth'),
path('hello', views.say_hello, name='hello'),
]
urls = include(urlpatterns)
Вы можете реализовать защиту для представлений, требующих учетных данных, как показано ниже.
import functools
import json
import urllib
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from django.shortcuts import redirect
from django.http import HttpResponse
SCOPES = ['https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', 'openid']
def provides_credentials(func):
@functools.wraps(func)
def wraps(request):
# If OAuth redirect response, get credentials
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES,
redirect_uri="http://localhost:8000/tweet/hello")
existing_state = request.GET.get('state', None)
current_path = request.path
if existing_state:
secure_uri = request.build_absolute_uri(
).replace('http', 'https')
location_path = urllib.parse.urlparse(existing_state).path
flow.fetch_token(
authorization_response=secure_uri,
state=existing_state
)
request.session['credentials'] = flow.credentials.to_json()
if location_path == current_path:
return func(request, flow.credentials)
# Head back to location stored in state when
# it is different from the configured redirect uri
return redirect(existing_state)
# Otherwise, retrieve credential from request session.
stored_credentials = request.session.get('credentials', None)
if not stored_credentials:
# It's strongly recommended to encrypt state.
# location is needed in state to remember it.
location = request.build_absolute_uri()
# Commence OAuth dance.
auth_url, _ = flow.authorization_url(state=location)
return redirect(auth_url)
# Hydrate stored credentials.
credentials = Credentials(**json.loads(stored_credentials))
# If credential is expired, refresh it.
if credentials.expired and creds.refresh_token:
creds.refresh(Request())
# Store JSON representation of credentials in session.
request.session['credentials'] = credentials.to_json()
return func(request, credentials=credentials)
return wraps
@provides_credentials
def google_oauth(request, credentials):
return HttpResponse('Google OAUTH <a href="/tweet/hello">Say Hello</a>')
@provides_credentials
def say_hello(request, credentials):
# Use credentials for whatever
return HttpResponse('Hello')
Обратите внимание, что это только пример. Если вы решите использовать go этот маршрут, я рекомендую изучить возможность извлечения потока OAuth в его собственное приложение Django.