我正在开发一个 SPA 应用程序AngularJS http://angularjs.org/它使用Django https://www.djangoproject.com/服务器的后端。我从 SPA 与服务器通信的方式是django-rest-framework https://github.com/tomchristie/django-rest-framework。所以现在我想用 facebook(谷歌和推特)进行身份验证,我阅读了很多关于这个主题的内容并发现OAuth.io https://oauth.io/这在客户端 SPA 端进行身份验证,并且python-社交-身份验证 https://github.com/omab/python-social-auth它在服务器端做同样的事情。
所以目前我只有客户端身份验证,我的应用程序正在连接到 facebook(使用 OAuth.io)并成功登录。此过程返回 access_token,然后我向我的 API 发出请求,该 API 必须登录此用户或通过给定令牌为此用户创建帐户,但这部分不起作用。所以我不确定我错在哪里,也许是因为没有关于使用 python-social-auth 的完整教程,所以也许我错过了一些东西或者..我不知道..
所以我有一些代码:
在 SPA 方面:这是与 OAuth.io 的连接,并且正在工作,因为我正在获取访问令牌。然后我必须向我的 REST 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');
});
});
在服务器上的 settings.py 中,我已将社交插件添加到已安装的应用程序、模板上下文预处理器、一些身份验证后端,这就是我的文件:
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',
)
在我的API的views.py中,我有以下内容(我发现它here http://blog.wizer.fr/2013/11/angularjs-facebook-with-a-django-rest-api/):
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
最后我在 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),
...
每次当我尝试进行身份验证时,OAuth.io 正在工作并且 api 的 rqest 返回
详细信息:“无效令牌”
我认为我错过了 python-social-auth 配置中的某些内容,或者我做错了一切。因此,如果有人有一些想法并想要提供帮助,我会很高兴:)