val*_*lov 28 facebook angularjs django-rest-framework python-social-auth
我正在使用AngularJS开发一个SPA应用程序,它使用Django后端作为服务器.我从SPA与服务器通信的方式是使用django-rest-framework.所以现在我想用facebook(google和twitter)进行身份验证,我在这个主题上阅读了很多内容,发现OAuth.io正在客户端SPA端进行验证,而python-social-auth正在做同样的事情但在服务器端.
所以目前我只有客户端身份验证,我的应用程序连接到Facebook(使用OAuth.io)并成功登录.此过程返回access_token然后我向我的API发出请求,该请求必须登录此用户或通过给定令牌为该用户创建帐户,此部分不起作用.所以我不确定我错在哪里,也许是因为没有关于使用python-social-auth的完整教程所以也许我错过了什么或者......我不知道..
所以我的一些代码:
在SPA方面:这是与OAuth.io的连接,并且正在工作,因为我正在获取访问令牌.然后我必须向我的其他API发出请求.后端是'facebook','google'或'twitter'
OAuth.initialize('my-auth-code-for-oauthio');
OAuth.popup(backend, function(error, result) {
//handle error with error
//use result.access_token in your API request
var token = 'Token ' + result.access_token;
var loginPromise = $http({
method:'POST',
url: 'api-token/login/' + backend + '/',
headers: {'Authorization': token}});
loginPromise.success(function () {
console.log('Succeess');
});
loginPromise.error(function (result) {
console.log('error');
});
});
Run Code Online (Sandbox Code Playgroud)
在我的settings.py中的服务器上,我已经为已安装的应用程序,模板上下文预处理器,一些auth后端添加了社交插件,这是我的文件:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
...,
'rest_framework',
'rest_framework.authtoken',
'api',
'social.apps.django_app.default',
'social'
)
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.core.context_processors.request",
"django.contrib.messages.context_processors.messages",
'social.apps.django_app.context_processors.backends',
'social.apps.django_app.context_processors.login_redirect',)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
SOCIAL_AUTH_FACEBOOK_KEY = 'key'
SOCIAL_AUTH_FACEBOOK_SECRET = 'secret'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
AUTHENTICATION_BACKENDS = (
'social.backends.open_id.OpenIdAuth',
'social.backends.facebook.FacebookOAuth2',
'social.backends.facebook.FacebookAppOAuth',
'social.backends.google.GoogleOpenId',
'social.backends.google.GoogleOAuth2',
'social.backends.google.GoogleOAuth',
'social.backends.twitter.TwitterOAuth',
'django.contrib.auth.backends.ModelBackend',
)
Run Code Online (Sandbox Code Playgroud)
在我的API的views.py中,我有以下内容(我在这里找到):
from django.contrib.auth.models import User, Group
from rest_framework import viewsets, generics
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions, parsers, renderers
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.decorators import api_view, throttle_classes
from social.apps.django_app.utils import strategy
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
class ObtainAuthToken(APIView):
throttle_classes = ()
permission_classes = ()
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
renderer_classes = (renderers.JSONRenderer,)
serializer_class = AuthTokenSerializer
model = Token
# Accept backend as a parameter and 'auth' for a login / pass
def post(self, request, backend):
serializer = self.serializer_class(data=request.DATA)
if backend == 'auth':
if serializer.is_valid():
token, created = Token.objects.get_or_create(user=serializer.object['user'])
return Response({'token': token.key})
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
# Here we call PSA to authenticate like we would if we used PSA on server side.
user = register_by_access_token(request, backend)
# If user is active we get or create the REST token and send it back with user data
if user and user.is_active:
token, created = Token.objects.get_or_create(user=user)
return Response({'id': user.id , 'name': user.username, 'userRole': 'user','token': token.key})
@strategy()
def register_by_access_token(request, backend):
backend = request.strategy.backend
user = request.user
user = backend._do_auth(
access_token=request.GET.get('access_token'),
user=user.is_authenticated() and user or None
)
return user
Run Code Online (Sandbox Code Playgroud)
最后我在urls.py中有这些路由:
...
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api-token-auth/', 'rest_framework.authtoken.views.obtain_auth_token'),
url(r'^api-token/login/(?P<backend>[^/]+)/$', views.ObtainAuthToken.as_view()),
url(r'^register/(?P<backend>[^/]+)/', views.register_by_access_token),
...
Run Code Online (Sandbox Code Playgroud)
每当我尝试执行身份验证时,OAuth.io正在运行,并且返回apq的rqest
详细信息:"无效令牌"
我认为我在python-social-auth的配置中遗漏了一些东西,或者我做错了什么.所以如果有人有想法并希望帮助我会很高兴:)
将以下行添加到ObtainAuthToken类
authentication_classes = ()
Run Code Online (Sandbox Code Playgroud)
并且您的错误{"详细信息":"无效令牌"}将消失.
这就是为什么......
您的请求包含以下标头
Authorization: Token yourAccessToken
Run Code Online (Sandbox Code Playgroud)
但您已在DEFAULT_AUTHENTICATION_CLASSES中定义了rest_framework.authentication.TokenAuthentication.
基于此,Django认为您要在执行令牌时执行令牌身份验证.它失败,因为这是facebook的访问令牌,并且在您的django*_token数据库中不存在,因此无效令牌错误.在您的情况下,您需要做的就是告诉Django不要对此视图使用TokenAuthentication.
FYI
请记住,在执行ObtainAuthToken的post方法之前,您的代码执行已停止,因此可能会遇到更多错误.个人在尝试单步执行代码时遇到错误
'DjangoStrategy' object has no attribute 'backend'
Run Code Online (Sandbox Code Playgroud)
上
backend = request.strategy.backend
Run Code Online (Sandbox Code Playgroud)
并通过改为来解决它
uri = ''
strategy = load_strategy(request)
backend = load_backend(strategy, backend, uri)
Run Code Online (Sandbox Code Playgroud)
此外,您应该更新您的register_by_access_token函数,因为它不与您引用的博客中的工作代码对齐.博客作者在这里发布了他的最新代码.如果你想用它来与像facebook这样的第三方进行身份验证,你的版本不会将令牌从auth标头中拉出来.
是啊.解决了.设置不正确,您需要添加权限.
REST_FRAMEWORK = {
# Use hyperlinked styles by default.
# Only used if the `serializer_class` attribute is not set on a view.
'DEFAULT_MODEL_SERIALIZER_CLASS':
'rest_framework.serializers.HyperlinkedModelSerializer',
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
Run Code Online (Sandbox Code Playgroud)
和一些关于管道的信息:
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'social.pipeline.social_auth.associate_by_email',
'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details'
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7696 次 |
| 最近记录: |