【问题标题】:Why am I be getting a 403 Forbidden error when using @csrf_exempt in AJAX request?为什么在 AJAX 请求中使用 @csrf_exempt 时会收到 403 Forbidden 错误?
【发布时间】:2015-03-15 10:13:58
【问题描述】:

我正在尝试在 Django 中编写一个非常基本的 AJAX 请求,并且在 Chrome Dev 和 Django 控制台中都不断收到 403 禁止错误。前几天我发布了一个类似的问题,并尝试了所有建议的解决方案,包括 @csrf_exempt (以排除这是否甚至是一个 csrf 问题),我尝试在 AJAX POST 请求中包含 csrfmiddlewaretoken: '{{ csrf_token }}' (数据下方),这也没有解决问题。这是我的代码。

def profile_listview(request, username,
    template_name=userena_settings.USERENA_PROFILE_DETAIL_TEMPLATE,
    extra_context=None, **kwargs):
    user = get_object_or_404(get_user_model(),
                             username__iexact=username)
    fullsalelist = Entry.objects.filter(author__username__iexact=username)

    @csrf_exempt
    def delete_object(request):
        if request.is_ajax():
            print "request is ajax"
            object_name = request.POST.get('entryname')
            targetobject = Entry.objects.get(headline=object_name)
            if request.user.username == targetobject.author:
                targetobject.delete()
                print "hello" 
            return HttpResponseRedirect('/storefront/')

以及模板中的AJAX代码:

<script type="text/javascript">
    var my_app = {
      username: "{{ request.user.username }}"  
    };
</script>

<script>
 $(document).ready(function() {
    $(".delete_button").click(function() {
        var id = $(this).attr('id');
        $.ajax({
            type: "POST",
            url: "/accounts/" + my_app.username + "/listview/",
            data: { entryname:id },
        });
        return false;
    });
});
</script>

网址

(r'^accounts/(?P<username>[\@\.\w-]+)/listview/$', profile_listview),

注意事项:

  1. 我在设置中打开了 csrf 中间件

  2. 在 jQuery AJAX 代码中,url 和 data 都在发送正确的信息

  3. 当我单击删除按钮时,我收到 403 禁止错误。

  4. 打印“request is ajax”不会在控制台(或任何地方)打印。

我也很困惑,因为我得到了相互矛盾的信息。有人告诉我应该通过 javascript (https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/) 添加 csrf 值。这给我留下了2个问题。 1. 这与在我的 POST 请求中添加 csrfmiddlewaretoken: '{{ csrf_token }}' 有何不同?和 2. 更重要的是,我在使用 @csrf_exempt 时仍然收到 403 错误这一事实是否让这成为一个有争议的问题?

【问题讨论】:

  • 但是您没有在请求中发送 csrf 令牌。
  • 添加 csrf_exempt 装饰器应该会消除该限制,但奇怪的是会返回 403。
  • 另一方面,您的 JavaScript 代码将无法处理服务器端 HttpResponseRedirect。您需要将其作为字符串传回,然后执行:top.location = json.redirect_url 例如。
  • 你确定你调用的是正确的视图吗?请告诉我们你urls.py
  • 我使用我的 URLS 以及包含处理 AJAX 请求的方法的方法 'profile_listview' 更新帖子。

标签: jquery ajax django


【解决方案1】:

@csrf_exempt 需要在 urls.py 调用的函数之前。在 OP 的示例中,delete_object 从未被调用,因为在调用没有装饰器的 profile_listview 时已经发生错误。

附带说明,如果 URL 不存在,可能会有类似的情况(使用 @csrf_exempt 但得到 403)。出于某种原因(安全性?),它将返回 403 而不是 404,因此很难调试。

【讨论】:

    【解决方案2】:

    据我了解,delete_object 是 profile_listview 中的一个函数,但 profile_listview 并没有调用它。因此,profile_listview 没有 http 响应。 贴出错误信息

    【讨论】:

    • 我最终将 AJAX 内容从 delete_object 移动到 profile_listview。所以我只是摆脱了 delete_object 函数并将其全部放入一个函数中。
    【解决方案3】:

    作为catavaran 认为你称之为错误的观点。您应该调用 delete_object 视图。例如,添加网址

    (r'^accounts/(?P<username>[\@\.\w-]+)/listview/delete_object$', delete_object)
    

    和 AJAX

    $.ajax({
            type: "POST",
            url: "/accounts/" + my_app.username + "/listview/delete_object",
            data: { entryname:id },
        });
    

    希望对你有帮助

    【讨论】:

    • 有道理,但 delete_object 目前是 INSIDE profile_listview 方法,所以应该可以正常工作吗?或者没有。
    • 我认为这应该适用于某种通用视图。但这看起来不是一个适当的通用观点。我不明白你的 django 如何处理 delete_object 函数。如果这应该可行,您能否提供文章来描述这种创建视图的方式
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-30
    • 2023-01-29
    • 1970-01-01
    • 2019-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多