【发布时间】:2018-03-09 17:39:06
【问题描述】:
我正在使用带有 Allauth + REST-Auth 的 Django 进行 SPA 社交登录,并成功设置了 Facebook、VK 和 Google 授权,但在添加 Twitter 时遇到了问题。它以 {"code":89,"message":"Invalid or expired token."} 结尾。 看起来我错过了一些“使用 Twitter 进行标准登录”的功能
这是我的尝试:
首先,我已经按照文档中的描述设置了 Twitter 登录端点:
class TwitterLogin(SocialLoginView):
serializer_class = TwitterLoginSerializer
adapter_class = CustomTwitterOAuthAdapter
它具有 post 方法,期望 access_token 和 token_secret 因此创建了重定向视图以接收来自 twitter 的重定向,完成登录并通过模板渲染将内部 django 令牌设置为浏览器 localStorage(带有几行 JS 行):
class TwitterReceiveView(APIView):
def get(self, request, *args, **kwargs):
access_token = request.query_params.get('oauth_token')
token_secret = request.query_params.get('oauth_verifier')
params = {'access_token': access_token,
'token_secret': token_secret}
try:
result = requests.post(settings.DOMAIN + reverse('tw_login'), data=params).text
result = json.loads(result)
except (requests.HTTPError, json.decoder.JSONDecodeError):
result = {}
access_token = result.get('access_token')
context = {'access_token': access_token}
return render(request, 'account/local_storage_setter.html',
context, content_type='text/html')
不得不提的是,我尝试了两种方法来启动进程(获取初始令牌) 1.使用标准allauth urlhttp://0.0.0.0:8080/accounts/twitter/login 2. 创建了另一个可以从 SPA 使用的视图(使用 lib python oauth2):
class TwitterGetToken(APIView):
def get(self, request, *args, **kwargs):
request_token_url = 'https://api.twitter.com/oauth/request_token'
authorize_url = 'https://api.twitter.com/oauth/authorize'
app = SocialApp.objects.filter(name='Twitter').first()
if app and app.client_id and app.secret:
consumer = oauth.Consumer(app.client_id, app.secret)
client = oauth.Client(consumer)
resp, content = client.request(request_token_url, "GET")
if resp['status'] != '200':
raise Exception("Invalid response {}".format(resp['status']))
request_token = dict(urllib.parse.parse_qsl(content.decode("utf-8")))
twitter_authorize_url = "{0}?oauth_token={1}"\
.format(authorize_url, request_token['oauth_token'])
return redirect(twitter_authorize_url)
raise Exception("Twitter app is not set up")
我什至尝试为 FacebookLoginView 编写 get 方法并直接将 twitter 回调传递给它
class TwitterLogin(SocialLoginView):
serializer_class = TwitterLoginSerializer
adapter_class = TwitterOAuthAdapter
def get(self, request, *args, **kwargs):
data = {
'access_token': request.query_params.get('oauth_token'),
'token_secret': request.query_params.get('oauth_verifier')
}
self.request = request
self.serializer = self.get_serializer(data=data,
context={'request': request})
self.serializer.is_valid(raise_exception=True)
self.login()
return self.get_response()
所有方法都导致我提到了错误。请您就我的情况提出一些建议。提前谢谢!
更新: 以下是它对我的工作方式:
import json
import requests
import urllib.parse
import oauth2 as oauth
from requests_oauthlib import OAuth1Session
from django.urls import reverse
from django.conf import settings
from django.shortcuts import redirect, render
from rest_framework.views import APIView
from allauth.socialaccount.models import SocialApp
from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter, TwitterAPI
from rest_auth.social_serializers import TwitterLoginSerializer
from rest_auth.registration.views import SocialLoginView
class TwitterGetToken(APIView):
'''
Initiates Twitter login process
Requests initial token and redirects user to Twitter
'''
def get(self, request, *args, **kwargs):
request_token_url = 'https://api.twitter.com/oauth/request_token'
authorize_url = 'https://api.twitter.com/oauth/authorize'
app = SocialApp.objects.filter(name='Twitter').first()
if app and app.client_id and app.secret:
consumer = oauth.Consumer(app.client_id, app.secret)
client = oauth.Client(consumer)
resp, content = client.request(request_token_url, "GET")
if resp['status'] != '200':
raise Exception("Invalid response {}".format(resp['status']))
request_token = dict(urllib.parse.parse_qsl(content.decode("utf-8")))
twitter_authorize_url = "{0}?oauth_token={1}"\
.format(authorize_url, request_token['oauth_token'])
return redirect(twitter_authorize_url)
raise Exception("Twitter app is not set up")
class TwitterLogin(SocialLoginView):
'''
Takes the final twitter access token, secret
Returns inner django Token
'''
serializer_class = TwitterLoginSerializer
adapter_class = TwitterOAuthAdapter
class TwitterReceiveView(APIView):
'''
Receives Twitter redirect,
Requests access token
Uses TwitterLogin to logn and get django Token
Renders template with JS code which sets django Token to localStorage and redirects to SPA login page
'''
def get(self, request, *args, **kwargs):
access_token_url = 'https://api.twitter.com/oauth/access_token'
callback_uri = settings.DOMAIN + '/accounts/twitter/login/callback/'
app = SocialApp.objects.filter(name='Twitter').first()
client_key = app.client_id
client_secret = app.secret
oauth_session = OAuth1Session(client_key,
client_secret=client_secret,
callback_uri=callback_uri)
redirect_response = request.get_full_path()
oauth_session.parse_authorization_response(redirect_response)
token = oauth_session.fetch_access_token(access_token_url)
params = {'access_token': token['oauth_token'],
'token_secret': token['oauth_token_secret']}
try:
result = requests.post(settings.DOMAIN + reverse('tw_login'),
data=params).text
result = json.loads(result)
except (requests.HTTPError, json.decoder.JSONDecodeError):
result = {}
access_token = result.get('access_token')
context = {'access_token': access_token,
'domain': settings.DOMAIN}
return render(request, 'account/local_storage_setter.html',
context, content_type='text/html')
【问题讨论】:
标签: python django django-allauth django-rest-auth