繁体   English   中英

如何在 Django 中通过 AJAX 设置令牌认证以保护 API url

[英]How to set token authentication via AJAX in Django to secure the API url

我正在使用 Django REST 框架来获取 JSON 中的数据,并使用它们通过 AJAX 刷新页面。 如何保护正在使用数据更新页面的 URL,并且没有人可以访问 API url。 该 url 在 AJAX 中的 html 中可见,因此可以访问它,但我想通过令牌或任何其他正确的身份验证来阻止它,只有访问它才有网站。

URL 是“/api/item/”(参见 AJAX 代码)

序列化程序.py

from rest_framework import serializers

from .models import Item

class ItemModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = [
            'title',
            'value',
        ]

views.py(在 API 中)

from rest_framework import generics
from .serializers import ItemModelSerializer
from .models import Item

class ItemListAPIView(generics.ListAPIView):
    serializer_class = ItemModelSerializer

    def get_queryset(self):
        return Item.objects.all().order_by('sort')

网址.py

urlpatterns = [
    #...urls...
    url(r'^api/item/', include('apps.item.api.urls', namespace='api-item')),
    url(r'^admin/', admin.site.urls),
]

模板 - ajax

setInterval(function() {
    $.ajax({
        method: "GET",
        url: "/api/item/",
        success: function(data) {
            $("#items tbody").empty();
            $.each(data, function (key, value) {                                      
                var itemKey = key;
                var itemTitle = value.title;  
                var itemValue = value.value;
                $("#items tbody").append(
                   "<tr><td class='left'>" + itemTitle + "</td><td>" + itemValue</td></tr>"
                )
            })
        },
        error: function(data) {
            console.log("error")
            console.log(data)
        }
    })
}, 3000)

我不确定我是否正确理解您的问题,我猜您是在问如何在 AJAX 中为 Django 中的 API 设置令牌。 通常,我们使用共享令牌的概念。 将有一个登录 API,它将使用用户名/密码对用户进行身份验证。 如果凭据正确,auth API 将返回您可以在 AJAX 请求中使用和设置的令牌。 使用该令牌进一步调用您的 API 以进行身份​​验证。

如果您想直接调用没有身份验证 API 的 API,则必须使用 Django 和 AJAX 之间共享的硬编码令牌,但是遵循这种做法是不安全的。

在这里查看 DRF 身份验证http://www.django-rest-framework.org/api-guide/authentication/#sessionauthentication

我做了类似的事情:

@Shwetabh Sharan 您将不得不使用 Django 和 AJAX 之间共享的硬编码令牌

@Shwetabh Sharan 说,但是,遵循这种做法是不安全的

到目前为止,没有人解决这个问题,即如何在 Django、AJAX、JS 中保护 GET 或 POST 请求,只有该网站可以使用它,其他人无法使用

他们总是推荐“JWT、令牌身份验证和会话身份验证”等。但是所有这些解决方案都需要用户注册,如果我想保护搜索自动完成字段或前端的任何公共内容会发生什么

我创建了一个休息框架自定义权限,我使用 django csrfmiddlewaretoken

它的行为与 Django post 表单相同,csrf 令牌中间件发送一个隐藏的输入类型{% csrf_token %} (输入隐藏与令牌)但这种情况只需要{{ csrf_token }} (令牌),Django 比较请求带有加密的 cookie 令牌的令牌

permission.py
    from django.middleware.csrf import _compare_salted_tokens, rotate_token
    from rest_framework.permissions import BasePermission


    class HasCsrfTokenValid(BasePermission):
        def has_permission(self, request, view):
            token_valid = False
            try:
                csrf_token = request.headers.get("api-csrftoken")
                csrf_cookie = request.META.get("CSRF_COOKIE")

                """
                Check if both alphanumerics(strings) values are differents to prevent 
                a malicious user get the csrf cookie and send it from the ajax.
                """
                if csrf_token == csrf_cookie:
                    rotate_token(request)
                    return False

                token_valid =  _compare_salted_tokens(csrf_token, csrf_cookie)
            except ValueError: # if csrf_token & csrf_cookie are not a valid alphanumeric
                return False
            return token_valid

将权限类添加到 api 视图

views.py
class SnippetSearchAPI(generics.ListAPIView):
    model = Snippet
    serializer_class = SnippetSearcSerializer
    permission_classes = [HasCsrfTokenValid,]
    queryset = Snippet.objects.all()

Ajax 请求:

$('#search-snippet').keyup(function () {
    $.ajax({
       url:"{% url 'snippet-search-space:api' %}",
       headers:{'api-csrftoken':'{{ csrf_token }}'},
       success:function(data){
         console.log(data)
       }
   });
 });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM