我使用Django和Allauth+restauth进行SPA社交登录,并成功地设置了Facebook、VK和Google授权,但在添加Twitter时遇到了一个问题。结果是{“code”:89,“message”:“Invalid or expired token.”} 我好像漏掉了什么东西,因为标准的Twitter登录是正常的
以下是我的尝试:
首先,我按照doc:
class TwitterLogin(SocialLoginView):
serializer_class = TwitterLoginSerializer
adapter_class = CustomTwitterOAuthAdapter
它具有post方法,需要access_token和token_secret 所以redirect view被创建来接收来自twitter的redirect,完成登录并通过template render(带有几行JS行)将内部django token设置为browser localStorage:
^{pr2}$必须提到,我尝试了两种方法来启动进程(获取初始令牌) 1使用标准allauth urlhttp://0.0.0.0:8080/accounts/twitter/login 2创建了另一个视图(使用lib python oauth2),可从SPA使用:
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')
伟大的代码,谢谢你的张贴!在
不过,我想补充的是,用户身份验证可以直接从前端完成,而且考虑到您正在编写一个SPA,这样做似乎是合乎逻辑的,而不是将您的后端(这打破了RESTful的概念)重定向到auth,然后发送响应。在
我使用了以下基于vue authenticate的JS helper类。弹出并从回调url获取信息
不过,我遵循的方法与您的方法相似:
其他的一切都会正常进行,用户会得到一个访问密钥。在
无论如何, 谢谢,我在js和python中处理了大量的库,但这只是最好的方法
相关问题 更多 >
编程相关推荐