在 django-rest-framework 中,是不是可以同时使用 oauth 和 session 身份验证?

Posted

技术标签:

【中文标题】在 django-rest-framework 中,是不是可以同时使用 oauth 和 session 身份验证?【英文标题】:In django-rest-framework, is it possible to use oauth and session authentication simultaneously?在 django-rest-framework 中,是否可以同时使用 oauth 和 session 身份验证? 【发布时间】:2018-06-17 13:35:35 【问题描述】:

这就是我想要做的事情:我正在构建一个金融应用程序。有一个 Web 组件,它使用 Django 模板和 jQuery 处理 AJAX 请求,还有一个移动客户端。

我的目标是对来自网络应用程序的 AJAX 请求使用基于会话的身份验证,使用 django-allauth 进行身份验证,使用 django-oauth-toolkit 对移动应用程序使用 OAUTH2。我正在使用 django-rest-framework 作为端点。

在我添加 OAUTH 中间件/身份验证后端之前,AJAX 行为运行良好。我的view.py 中的这段代码现在在通过 AJAX 调用访问时会提示 401 未经授权,即使用户使用 django-allauth 进行身份验证也是如此。它以前工作过(并且在使用访问令牌通过 curl 访问时仍然工作):

@api_view(['GET'])
def portfolio(request):
    """
    Get account balances, total portfolio value in CAD, and balances converted to CAD at current market rates.
    """
    try:
        account = request.user.account
    except ObjectDoesNotExist:
        return Response(status=Status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = AccountSerializer(account)
        return Response(serializer.data)

这里是mysettings.py的相关位:

MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'oauth2_provider.middleware.OAuth2TokenMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django_otp.middleware.OTPMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

AUTHENTICATION_BACKENDS = (
    'allauth.account.auth_backends.AuthenticationBackend',
    'django.contrib.auth.backends.ModelBackend',
    'oauth2_provider.backends.OAuth2Backend',
)

我编写的不使用 django-rest 的旧方法仍然可以正常工作:

@verified_account_required
def get_rates(request):
    if request.method == 'POST':
        buy_rates,sell_rates = utility_rates()

        if request.POST.get('action') == 'buy':
            data = buy_rates
        else:
            data = sell_rates

        return JsonResponse(data)

如何同时使用 Django-rest 和两种身份验证类型?还是不可能?

诚然,我对 Django 很陌生 - 所以这里可能有一些我没有正确理解的东西。

【问题讨论】:

【参考方案1】:

我在此设置中使用基于类的视图,但我的设置有一个不同:

REST_FRAMEWORK = 
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
    ),

然后在 API 视图中,我有以下内容:

from rest_framework import viewsets, permissions, authentication
from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope, OAuth2Authentication
from . import models, serializers

class MyViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.MySerializer
    authentication_classes = [OAuth2Authentication, authentication.SessionAuthentication]
    permission_classes = [IsAuthenticatedOrTokenHasScope,]
    required_scopes = ['scope',]

一切正常。

但是,确实,在 DRF 设置的 DEFAULT_AUTHENTICATION_CLASSES 中添加 'oauth2_provider.contrib.rest_framework.OAuth2Authentication' 不起作用。可能是 OAuth2 身份验证后端抛出 401,因为它在 AJAX 请求中没有找到 Token,并且 DRF 没有处理它以给 SessionAuthentication 第二次机会。

我希望这能给您在基于函数的视图中使用 OAuth2 的提示。

【讨论】:

以上是关于在 django-rest-framework 中,是不是可以同时使用 oauth 和 session 身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

django-rest-framework - 在可浏览的 API 中自动生成表单?

在带有 django-rest-framework 的过滤器中使用自定义方法

如何在 React 中显示来自 django-rest-framework 的错误消息

断言错误:Django-rest-Framework

django-rest-framework 序列化器在多个视图中的不同字段

将 django-rest-framework 中的超链接添加到 ModelViewSet