简体   繁体   English

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

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

I am using Django REST framework to have data available in JSON and using them to refresh the page via AJAX.我正在使用 Django REST 框架来获取 JSON 中的数据,并使用它们通过 AJAX 刷新页面。 How can I secure the URL that page is being updated with data and no one can access the API url.如何保护正在使用数据更新页面的 URL,并且没有人可以访问 API url。 The url is visible in AJAX in html so it can be accessed but I would like to prevent it by token or any other proper authentication that only access to it has website.该 url 在 AJAX 中的 html 中可见,因此可以访问它,但我想通过令牌或任何其他正确的身份验证来阻止它,只有访问它才有网站。

The URL is '/api/item/' (see in the AJAX code) URL 是“/api/item/”(参见 AJAX 代码)

serializers.py序列化程序.py

from rest_framework import serializers

from .models import Item

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

views.py (in API) 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')

urls.py网址.py

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

template - ajax模板 - 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)

I'm not sure if I understand your question correctly, I guess you are asking how do you set a token in AJAX for your API in Django.我不确定我是否正确理解您的问题,我猜您是在问如何在 AJAX 中为 Django 中的 API 设置令牌。 Usually, we use a concept of shared token.通常,我们使用共享令牌的概念。 There will be a login API which will authenticate a user with a username/password.将有一个登录 API,它将使用用户名/密码对用户进行身份验证。 If the credentials are correct, auth API will return the token which you can use and set in AJAX requests.如果凭据正确,auth API 将返回您可以在 AJAX 请求中使用和设置的令牌。 Use that token to make further calls to your API for authentication.使用该令牌进一步调用您的 API 以进行身份​​验证。

If you directly want to call your API without auth API, you will have to use a hard coded token shared between Django and AJAX however it is unsafe to follow such practices.如果您想直接调用没有身份验证 API 的 API,则必须使用 Django 和 AJAX 之间共享的硬编码令牌,但是遵循这种做法是不安全的。

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

I have done something similar to this:我做了类似的事情:

@Shwetabh Sharan you will have to use a hardcoded token shared between Django and AJAX @Shwetabh Sharan 您将不得不使用 Django 和 AJAX 之间共享的硬编码令牌

But

@Shwetabh Sharan says, however, it is unsafe to follow such practices @Shwetabh Sharan 说,但是,遵循这种做法是不安全的

So far no one has addressed this issue how to secure GET or POST requests in Django, AJAX, JS only that website can use it nobody else到目前为止,没有人解决这个问题,即如何在 Django、AJAX、JS 中保护 GET 或 POST 请求,只有该网站可以使用它,其他人无法使用

they always recommend "JWT, token authentication and session authentication", etc. But all those solutions require a user registered, and what happens if I want to protect a search autocomplete field or anything on the frontend that is public他们总是推荐“JWT、令牌身份验证和会话身份验证”等。但是所有这些解决方案都需要用户注册,如果我想保护搜索自动完成字段或前端的任何公共内容会发生什么

I have created a rest framework custom permission and I using django csrfmiddlewaretoken我创建了一个休息框架自定义权限,我使用 django csrfmiddlewaretoken

it behaves the same like Django post form, csrf token middleware send an input type hidden with {% csrf_token %} (input hidden with the token) but and this case only needs {{ csrf_token }} (the token), Django compares the request token with cookie token which are encrypted它的行为与 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

add permission class to api view将权限类添加到 api 视图

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

Ajax request: 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