Facebook Auth与AngularJS和Django REST框架

 mobiledu2502912375 发布于 2023-02-08 09:08

我正在使用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');
         });
});

在我的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',
  )

在我的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

最后我在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[^/]+)/$', views.ObtainAuthToken.as_view()),
url(r'^register/(?P[^/]+)/', views.register_by_access_token),
...

每当我尝试执行身份验证时,OAuth.io正在运行,并且返回apq的rqest

详细信息:"无效令牌"

我认为我在python-social-auth的配置中遗漏了一些东西,或者我做错了什么.所以如果有人有想法并希望帮助我会很高兴:)

2 个回答
  • 将以下行添加到ObtainAuthToken类

    authentication_classes = ()
    

    并且您的错误{"详细信息":"无效令牌"}将消失.

    这就是为什么......

    您的请求包含以下标头

    Authorization: Token yourAccessToken
    

    但您已在DEFAULT_AUTHENTICATION_CLASSES中定义了rest_framework.authentication.TokenAuthentication.

    基于此,Django认为您要在执行令牌时执行令牌身份验证.它失败,因为这是facebook的访问令牌,并且在您的django*_token数据库中不存在,因此无效令牌错误.在您的情况下,您需要做的就是告诉Django不要对此视图使用TokenAuthentication.

    FYI

    请记住,在执行ObtainAuthToken的post方法之前,您的代码执行已停止,因此可能会遇到更多错误.个人在尝试单步执行代码时遇到错误

    'DjangoStrategy' object has no attribute 'backend'
    

    backend = request.strategy.backend
    

    并通过改为来解决它

    uri = ''
    strategy = load_strategy(request)
    backend = load_backend(strategy, backend, uri)
    

    此外,您应该更新您的register_by_access_token函数,因为它不与您引用的博客中的工作代码对齐.博客作者在这里发布了他的最新代码.如果你想用它来与像facebook这样的第三方进行身份验证,你的版本不会将令牌从auth标头中拉出来.

    2023-02-08 09:12 回答
  • 是啊.解决了.设置不正确,您需要添加权限.

     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'
         ]
     }
    

    和一些关于管道的信息:

     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'
     )
    

    2023-02-08 09:13 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有