当请求来自用户登录的页面时,自动验证 DRF。如果从外部发出 api 请求,则请求令牌身份验证

Vla*_*col 2 authentication django django-rest-framework

我已经覆盖了自定义用户模型,以便我可以使用电子邮件而不是用户名登录,并且可以在首次登录时重定向到更改密码。

def login_view(request):
    if request.method == 'POST':
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            user = form.get_user()
            if user.last_login is None:
                login(request, user)
                return redirect('accounts:change_password')
            else:
                login(request, user)
                return redirect('home')
    else:
        form = AuthenticationForm()

    if request.user.is_authenticated:
        return redirect('home')
    else:
        return render(request, 'login.html', {'form': form})
Run Code Online (Sandbox Code Playgroud)

我已经使用 DRF 设置了一个基本的 Rest API 端点

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
Run Code Online (Sandbox Code Playgroud)

当我访问主页时,我需要登录:

@login_required(login_url="/accounts/login/")
def home(request):
    return render(request, 'index.html', {})
Run Code Online (Sandbox Code Playgroud)

我想做的是使用 django.contrib.auth 进行身份验证并重定向到主页。

当主页加载时,我想执行 AJAX 调用来显示所有用户。

$.ajax(
    {
        type: "GET",
        url: '/accounts/users/',
        success: function(result){
                 console.log(result);
                }
    });
Run Code Online (Sandbox Code Playgroud)

仅当我已经使用我的用户登录时,此调用才应有效。

如果我从外部访问端点,比如说在 Postman 中,它应该要求我进行身份验证。

我应该能够使用令牌身份验证在邮递员中进行外部身份验证。


问题:

如何以上述方式将 django.contrib.auth 身份验证与 Django Rest_framework 令牌身份验证混合在一起?我想同时拥有一个 Web 应用程序和一个 REST API。使用 django.contrib.auth 在 Web 应用程序中进行身份验证。使用 Token 对 REST API 进行身份验证。但是,如果用户已经登录 Web 应用程序,则执行 Rest API 请求而无需再次进行身份验证。我可以以某种方式重用 Web 应用程序会话吗?


已经自定义了我的用户模型: https://docs.djangoproject.com/en/2.1/topics/auth/customizing/

看过了,还没开始实施。我不确定他们如何连接。 https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication



解决方案

尽管我同时找到了解决方案,但我接受了下面的答案。我假设您只能添加一种身份验证方法,但您可以有更多方法。我实际上最终做的是:

'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.TokenAuthentication',
    'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
    'rest_framework.permissions.IsAuthenticated',
)
Run Code Online (Sandbox Code Playgroud)

它就像一个魅力。在我的例子中,IsAuthenticated 权限在全局范围内应用。在接受的答案中应用每个端点

Ken*_*ars 6

您始终可以根据需要使用任意多种身份验证方法。除了 TokenAuthentication 之外,DRF 还具有与本机 Django 身份验证类似的SessionAuthentication 。您所需要做的就是在设置文件中全局设置两个身份验证类或按视图设置。

例如,您可以UserViewSet通过这种方式设置您的身份验证类别。

from rest_framework.authentication import TokenAuthentication, SessionAuthentication


class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    authentication_classes = [TokenAuthentication, SessionAuthentication]
Run Code Online (Sandbox Code Playgroud)

这样,您的 Web 客户端就可以使用会话进行身份验证,而其他客户端则使用令牌。