การตรวจสอบ Django CSRF ล้มเหลวด้วยคำขอ Ajax POST


180

ฉันสามารถใช้ความช่วยเหลือเพื่อให้สอดคล้องกับกลไกการป้องกัน CSRF ของ Django ผ่านทางโพสต์ AJAX ของฉัน ฉันได้ทำตามคำแนะนำที่นี่:

http://docs.djangoproject.com/en/dev/ref/contrib/csrf/

ฉันได้คัดลอกโค้ดตัวอย่าง AJAX ที่มีในหน้านั้นอย่างแน่นอน:

http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

ฉันใส่การแจ้งเตือนการพิมพ์เนื้อหาของgetCookie('csrftoken')ก่อนxhr.setRequestHeaderโทรและมันแน่นอนมีประชากรด้วยข้อมูลบางอย่าง ฉันไม่แน่ใจว่าจะยืนยันได้อย่างไรว่าโทเค็นนั้นถูกต้อง แต่ฉันขอแนะนำให้หาและส่งบางสิ่งบางอย่าง

แต่ Django ยังคงปฏิเสธโพสต์ AJAX ของฉัน

นี่คือ JavaScript ของฉัน:

$.post("/memorize/", data, function (result) {
    if (result != "failure") {
        get_random_card();
    }
    else {
        alert("Failed to save card data.");
    }
});

นี่เป็นข้อผิดพลาดที่ฉันเห็นจาก Django:

[23 / Feb / 2011 22:08:29] "POST / จดจำ / HTTP / 1.1" 403 2332

ฉันแน่ใจว่าฉันพลาดบางสิ่งบางอย่างและอาจจะง่าย แต่ฉันไม่รู้ว่ามันคืออะไร ฉันค้นหารอบ ๆ และเห็นข้อมูลบางอย่างเกี่ยวกับการปิดการตรวจสอบ CSRF สำหรับมุมมองของฉันผ่านทางcsrf_exemptมัณฑนากร แต่ฉันพบว่าไม่น่าสนใจ ฉันลองแล้วมันใช้งานได้ แต่ฉันอยากให้ POST ทำงานตามวิธีที่ Django ออกแบบมาเพื่อคาดหวังถ้าเป็นไปได้

ในกรณีที่เป็นประโยชน์นี่เป็นส่วนสำคัญของสิ่งที่ฉันทำมุมมอง:

def myview(request):

    profile = request.user.profile

    if request.method == 'POST':
        """
        Process the post...
        """
        return HttpResponseRedirect('/memorize/')
    else: # request.method == 'GET'

        ajax = request.GET.has_key('ajax')

        """
        Some irrelevent code...
        """

        if ajax:
            response = HttpResponse()
            profile.get_stack_json(response)
            return response
        else:
            """
            Get data to send along with the content of the page.
            """

        return render_to_response('memorize/memorize.html',
                """ My data """
                context_instance=RequestContext(request))

ขอบคุณสำหรับคำตอบของคุณ!


1
คุณกำลังใช้ django รุ่นใดอยู่
zsquare

คุณได้เพิ่มคลาสมิดเดิลแวร์ของ CSRF ที่ถูกต้องและวางไว้ในลำดับที่ถูกต้องหรือไม่?
darren

Jakub ตอบคำถามของฉันด้านล่าง แต่ในกรณีที่เป็นประโยชน์กับคนอื่น: @zsquare: รุ่น 1.2.3 @mongoose_za: ใช่พวกเขาจะถูกเพิ่มและในลำดับที่ถูกต้อง
firebush

คำตอบ:


181

ทางออกที่แท้จริง

ตกลงฉันจัดการเพื่อติดตามปัญหาลง มันอยู่ในรหัส Javascript (ตามที่ฉันแนะนำด้านล่าง)

สิ่งที่คุณต้องการคือ:

$.ajaxSetup({ 
     beforeSend: function(xhr, settings) {
         function getCookie(name) {
             var cookieValue = null;
             if (document.cookie && document.cookie != '') {
                 var cookies = document.cookie.split(';');
                 for (var i = 0; i < cookies.length; i++) {
                     var cookie = jQuery.trim(cookies[i]);
                     // Does this cookie string begin with the name we want?
                     if (cookie.substring(0, name.length + 1) == (name + '=')) {
                         cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                         break;
                     }
                 }
             }
             return cookieValue;
         }
         if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
             // Only send the token to relative URLs i.e. locally.
             xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
         }
     } 
});

แทนที่จะเป็นรหัสที่โพสต์ในเอกสารอย่างเป็นทางการ: https://docs.djangoproject.com/en/2.2/ref/csrf/

รหัสการทำงานมาจากรายการ Django นี้: http://www.djangoproject.com/weblog/2011/feb/08/security/

ดังนั้นวิธีแก้ปัญหาทั่วไปคือ: "ใช้ ajaxSetup handler แทน ajaxSend handler" ฉันไม่รู้ว่าทำไมมันถึงได้ผล แต่มันเหมาะกับฉัน :)

โพสต์ก่อนหน้า (ไม่มีคำตอบ)

ฉันประสบปัญหาเดียวกันจริง ๆ แล้ว

มันเกิดขึ้นหลังจากอัพเดตเป็น Django 1.2.5 - ไม่มีข้อผิดพลาดกับการร้องขอ AJAX POST ใน Django 1.2.4 (AJAX ไม่ได้รับการปกป้อง แต่อย่างใด แต่ก็ใช้ได้ดี)

เช่นเดียวกับ OP ฉันได้ลองใช้ตัวอย่างโค้ด JavaScript ที่โพสต์ในเอกสาร Django ฉันใช้ jQuery 1.5 ฉันยังใช้มิดเดิลแวร์ "django.middleware.csrf.CsrfViewMiddleware"

ฉันพยายามติดตามรหัสมิดเดิลแวร์และฉันรู้ว่ามันล้มเหลวในเรื่องนี้:

request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

แล้ว

if request_csrf_token != csrf_token:
    return self._reject(request, REASON_BAD_TOKEN)

สิ่งนี้ "ถ้า" เป็นจริงเพราะ "request_csrf_token" ว่างเปล่า

โดยทั่วไปหมายความว่าไม่ได้ตั้งค่าส่วนหัว ดังนั้นจะมีอะไรผิดปกติกับสาย JS นี้:

xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));

?

ฉันหวังว่ารายละเอียดที่ให้ไว้จะช่วยเราในการแก้ไขปัญหา :)


ใช้งานได้! ฉันใส่ฟังก์ชัน. jaxetupup ตามที่คุณวางไว้ด้านบนและตอนนี้ฉันสามารถโพสต์โดยไม่มีข้อผิดพลาด 403 ขอบคุณสำหรับการแบ่งปันโซลูชันจาคุบ หาดี :)
firebush

การใช้ajaxSetupแทนการajaxSendรันตัวนับเอกสาร jQuery: api.jquery.com/jQuery.ajaxSetup
Mark Lavin

ใช้ 1.3 รายการเอกสาร django อย่างเป็นทางการใช้ได้สำหรับฉัน
monkut

1
ฉันลองแล้ว แต่ดูเหมือนจะไม่เหมาะกับฉันฉันใช้ jQuery v1.7.2 คำถามของฉันคือstackoverflow.com/questions/11812694/…
daydreamer

ฉันต้องเพิ่มคำอธิบายประกอบ@ensure_csrf_cookieไปยังฟังก์ชันมุมมองของฉันเพื่อบังคับให้ตั้งค่าคุกกี้csrfเมื่อมีการร้องขอหน้าเว็บจากอุปกรณ์มือถือ
เทอรีเคน

172

หากคุณใช้$.ajaxฟังก์ชั่นคุณสามารถเพิ่มcsrfโทเค็นในส่วนเนื้อหาได้:

$.ajax({
    data: {
        somedata: 'somedata',
        moredata: 'moredata',
        csrfmiddlewaretoken: '{{ csrf_token }}'
    },

2
เมื่อฉันใช้คำตอบที่ทำเครื่องหมายไว้มันใช้ได้ผลสำหรับฉัน แต่ถ้าฉันใช้วิธีแก้ปัญหาของคุณที่นี่มันก็ไม่ได้ แต่วิธีการแก้ปัญหาของคุณควรทำงานฉันไม่เข้าใจว่าทำไมมันไม่ มีอะไรอีกบ้างที่ต้องทำใน Django 1.4?
Houman

1
ขอบคุณ! ง่ายมาก ยังคงใช้งานได้กับ django 1.8 และ jQuery 2.1.3
Alejandro Veintimilla

19
วิธีการแก้ปัญหานี้ต้องใช้จาวาสคริปต์ที่จะฝังตัวอยู่ในแม่แบบมันได้หรือไม่
Mox

15
@Mox: ใส่สิ่งนี้ใน html แต่เหนือไฟล์ Js ของคุณซึ่งเป็นฟังก์ชั่น ajax <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
HereHere

ขอบคุณ! เรียบง่ายและสง่างาม มันใช้งานได้สำหรับฉันกับ Django 1.8 ฉันเพิ่มลงcsrfmiddlewaretoken: '{{ csrf_token }}'ในdataพจนานุกรมของฉันในการ$.postโทร
Pavel Yudaev

75

เพิ่มบรรทัดนี้ในรหัส jQuery ของคุณ:

$.ajaxSetup({
  data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});

และทำ


ฉันลองสิ่งนี้ยกเว้นแบบฟอร์มของฉันมีการอัปโหลดไฟล์ แบ็คเอนด์ของฉันคือ django และยังได้รับข้อผิดพลาด 400CSRF Failed: CSRF token missing or incorrect.
Hussain

16

ปัญหานี้เกิดขึ้นเนื่องจาก django คาดว่าค่าจากคุกกี้จะถูกส่งกลับเป็นส่วนหนึ่งของข้อมูลในแบบฟอร์ม รหัสจากคำตอบก่อนหน้าคือการรับจาวาสคริปต์เพื่อค้นหามูลค่าคุกกี้และใส่ลงในแบบฟอร์มข้อมูล นั่นเป็นวิธีที่น่ารักในการทำจากมุมมองทางเทคนิค แต่มันดูค่อนข้างละเอียด

ในอดีตที่ผ่านมาฉันทำมันง่ายขึ้นโดยการใช้จาวาสคริปต์เพื่อใส่ค่าโทเค็นลงในข้อมูลโพสต์

หากคุณใช้ {% csrf_token%} ในแม่แบบของคุณคุณจะได้รับฟิลด์ที่ซ่อนอยู่ซึ่งปล่อยออกมาซึ่งมีค่า แต่ถ้าคุณใช้ {{csrf_token}} คุณจะได้รับค่าโทเค็นที่ไม่เปิดเผยดังนั้นคุณสามารถใช้สิ่งนี้ในจาวาสคริปต์แบบนี้ ....

csrf_token = "{{ csrf_token }}";

จากนั้นคุณสามารถรวมสิ่งนั้นด้วยชื่อคีย์ที่จำเป็นในแฮชจากนั้นคุณส่งเป็นข้อมูลไปยังการโทร ajax


@aehlke คุณสามารถมีไฟล์คงที่ได้ ในซอร์สโค้ดคุณสามารถดูตัวอย่างที่ดีที่คุณลงทะเบียนตัวแปร djangoในwindowวัตถุเพื่อให้สามารถเข้าถึงได้หลังจากนั้น แม้ในไฟล์คงที่
KitKat

3
@KitKat แน่นอน :) ขออภัยสำหรับความคิดเห็นโบราณที่ไม่รู้ของฉันที่นี่ จุดดี.
aehlke

ไฟล์คงที่อีกครั้ง ไม่ใช่ปัญหาถ้าคุณไม่สนใจ js html ของคุณเล็กน้อย ฉันเพิ่งใส่ {{csrf_token}} ในเทมเพลต html หลักซึ่งอยู่ไม่ไกลจากคาถา requirejs ทำงานเหมือนจับใจ
JL Peyret

14

{% csrf_token %}ใส่ใน html แม่แบบภายใน<form></form>

แปลเป็นดังนี้:

<input type='hidden' name='csrfmiddlewaretoken' value='Sdgrw2HfynbFgPcZ5sjaoAI5zsMZ4wZR' />

ดังนั้นทำไมไม่เพียง grep ใน JS ของคุณเช่นนี้:

token = $("#change_password-form").find('input[name=csrfmiddlewaretoken]').val()

แล้วผ่านมันไปเช่นทำ POST บางอย่างเช่น:

$.post( "/panel/change_password/", {foo: bar, csrfmiddlewaretoken: token}, function(data){
    console.log(data);
});

11

คำตอบที่ไม่ใช่ jquery:

var csrfcookie = function() {
    var cookieValue = null,
        name = 'csrftoken';
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
};

การใช้งาน:

var request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.setRequestHeader('X-CSRFToken', csrfcookie());
request.onload = callback;
request.send(data);

8

ถ้าแบบฟอร์มของคุณโพสต์อย่างถูกต้องใน Django ที่ไม่มี JS คุณควรจะสามารถปรับปรุงให้ดีขึ้นด้วย ajax โดยไม่ต้องผ่านการแฮ็คหรือยุ่งเหยิงผ่านโทเค็น csrf เพียงเรียงลำดับแบบฟอร์มทั้งหมดและจะรับฟิลด์แบบฟอร์มทั้งหมดของคุณโดยอัตโนมัติรวมถึงฟิลด์ csrf ที่ซ่อนอยู่:

$('#myForm').submit(function(){
    var action = $(this).attr('action');
    var that = $(this);
    $.ajax({
        url: action,
        type: 'POST',
        data: that.serialize()
        ,success: function(data){
            console.log('Success!');
        }
    });
    return false;
});

ฉันได้ทำการทดสอบกับ Django 1.3+ และ jQuery 1.5+ แล้ว เห็นได้ชัดว่าวิธีนี้ใช้ได้กับรูปแบบ HTML ใด ๆ ไม่ใช่เฉพาะแอพ Django


5

ใช้ Firefox ด้วย Firebug เปิดแท็บ 'คอนโซล' ในขณะที่ไล่คำขอ ajax กับDEBUG=Trueคุณได้รับหน้าข้อผิดพลาด django ที่ดีเป็นการตอบสนองและคุณยังสามารถดู html ที่แสดงผลของการตอบสนอง ajax ในแท็บคอนโซล

จากนั้นคุณจะรู้ว่าข้อผิดพลาดคืออะไร


5

คำตอบที่ยอมรับได้มักเป็นปลาเฮอริ่งแดง ข้อแตกต่างระหว่าง Django 1.2.4 และ 1.2.5 คือข้อกำหนดสำหรับโทเค็น CSRF สำหรับคำขอ AJAX

ฉันเจอปัญหานี้ใน Django 1.3 และมันเกิดจากคุกกี้ CSRF ไม่ได้ถูกกำหนดไว้ตั้งแต่แรก Django จะไม่ตั้งค่าคุกกี้นอกจากจะต้องทำ ดังนั้นไซต์ ajax ที่เป็นเอกสิทธิ์หรือหนักมากที่ทำงานบน Django 1.2.4 อาจไม่เคยส่งโทเค็นไปยังไคลเอนต์จากนั้นการอัพเกรดที่ต้องใช้โทเค็นจะทำให้เกิดข้อผิดพลาด 403

การแก้ไขในอุดมคติอยู่ที่นี่: http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#page-uses-ajax-without-any-html-form
แต่คุณต้องรอ 1.4 เว้นแต่ นี่เป็นเพียงแค่เอกสารที่ใช้อ้างอิงกับโค้ด

แก้ไข

โปรดทราบว่าเอกสาร Django ในภายหลังบันทึกข้อบกพร่องใน jQuery 1.5 เพื่อให้แน่ใจว่าคุณกำลังใช้ 1.5.1 หรือใหม่กว่าด้วยรหัสแนะนำ Django: http://docs.djangoproject.com/en/1.3/ref/contrib/csrf/# อาแจ็กซ์


คำตอบของฉันถูกต้องในขณะที่เขียนมัน :) มันเป็นหลังจาก Django ได้รับการปรับปรุงจาก 1.2.4 เป็น 1.2.5 มันเป็นเช่นกันเมื่อ jQuery เวอร์ชันใหม่ล่าสุดคือ 1.5 ปรากฎว่ามีปัญหาเกิดขึ้นจากข้อผิดพลาด jQuery (1.5) และข้อมูลนี้จะถูกเพิ่มลงใน Django doc ตามที่คุณระบุไว้ ในกรณีของฉัน: คุกกี้ถูกตั้งค่าและโทเค็นไม่ได้ถูกเพิ่มลงในคำขอ AJAX การแก้ไขที่ได้รับทำงานได้กับ jQuery 1.5 ที่บั๊ก ณ ตอนนี้คุณสามารถแนบเอกสารทางการโดยใช้โค้ดตัวอย่างที่ให้ไว้และใช้ jQuery ใหม่ล่าสุด ปัญหาของคุณมีแหล่งที่มาที่แตกต่างจากปัญหาที่เกิดขึ้นกล่าวถึงที่นี่ :)
ยาคุบบGocławski

2
ขณะนี้มีผู้ตกแต่งที่เรียกensure_csrf_cookieว่าคุณสามารถล้อมรอบมุมมองเพื่อให้แน่ใจว่ามันจะส่งคุกกี้
Brian Neal

นี่คือปัญหาที่ฉันมีไม่มีcsrftokenคุกกี้ในตอนแรกขอบคุณ!
crhodes

5

ดูเหมือนว่าไม่มีใครพูดถึงวิธีการทำเช่นนี้ใน JS บริสุทธิ์โดยใช้X-CSRFTokenส่วนหัวและ{{ csrf_token }}นี่คือวิธีแก้ปัญหาง่ายๆที่คุณไม่จำเป็นต้องค้นหาผ่านคุกกี้หรือ DOM:

var xhttp = new XMLHttpRequest();
xhttp.open("POST", url, true);
xhttp.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
xhttp.send();

4

เนื่องจากไม่มีการระบุไว้ในคำตอบปัจจุบันทางออกที่เร็วที่สุดหากคุณไม่ได้ฝัง js ไว้ในเทมเพลตของคุณคือ:

ใส่<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>ก่อนการอ้างอิงถึงไฟล์ script.js ในเทมเพลตของคุณจากนั้นเพิ่มcsrfmiddlewaretokenลงในdataพจนานุกรมของคุณในไฟล์ js ของคุณ:

$.ajax({
            type: 'POST',
            url: somepathname + "do_it/",
            data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
            success: function() {
                console.log("Success!");
            }
        })

2

ฉันเพิ่งพบสถานการณ์ที่แตกต่างกันเล็กน้อย แต่ที่คล้ายกัน ไม่แน่ใจ 100% ว่าจะเป็นการแก้ปัญหาของคุณหรือไม่ แต่ฉันแก้ไขปัญหาสำหรับ Django 1.3 ด้วยการตั้งค่าพารามิเตอร์ POST 'csrfmiddlewaretoken' ด้วยสตริงค่าคุกกี้ที่เหมาะสมซึ่งโดยปกติจะส่งคืนภายในรูปแบบ HTML ที่บ้านของคุณโดย Django ระบบเทมเพลตที่มีแท็ก '{% csrf_token%}' ฉันไม่ได้ลอง Django ที่เก่ากว่าเพิ่งเกิดขึ้นและแก้ไขกับ Django1.3 ปัญหาของฉันคือว่าคำขอแรกที่ส่งผ่าน Ajax จากแบบฟอร์มเสร็จสมบูรณ์ แต่ความพยายามครั้งที่สองจากที่แน่นอนเดียวกันจากที่ล้มเหลวส่งผลให้สถานะ 403 แม้ว่าส่วนหัว 'X-CSRFToken' ถูกวางอย่างถูกต้องด้วยค่าโทเค็น CSRF เช่นกัน เช่นเดียวกับในกรณีของความพยายามครั้งแรก หวังว่านี่จะช่วยได้

ความนับถือ,

ไฮโร


2

คุณสามารถวาง js นี้ลงในไฟล์ html ของคุณจำไว้ก่อนหน้าฟังก์ชั่น js อื่น ๆ

<script>
  // using jQuery
  function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
      var cookies = document.cookie.split(';');
      for (var i = 0; i < cookies.length; i++) {
        var cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) == (name + '=')) {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  }

  function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  }

  $(document).ready(function() {
    var csrftoken = getCookie('csrftoken');
    $.ajaxSetup({
      beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
          xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
      }
    });
  });
</script>


1

หนึ่งโทเค็น CSRF ถูกกำหนดให้กับทุกเซสชัน (เช่นทุกครั้งที่คุณเข้าสู่ระบบ) ดังนั้นก่อนที่คุณต้องการรับข้อมูลที่ป้อนโดยผู้ใช้และส่งเป็น ajax ไปยังฟังก์ชันที่ได้รับการป้องกันโดยมัณฑนากร csrf_protect พยายามค้นหาฟังก์ชั่นที่ถูกเรียกก่อนที่คุณจะได้รับข้อมูลนี้จากผู้ใช้ เช่นเทมเพลตบางตัวต้องแสดงผลให้ผู้ใช้ของคุณป้อนข้อมูล เทมเพลตนั้นกำลังถูกแสดงผลโดยฟังก์ชั่นบางอย่าง ในฟังก์ชั่นนี้คุณจะได้รับโทเค็น csrf ดังนี้ csrf = request.COOKIES ['csrftoken'] ตอนนี้ผ่านค่า csrf นี้ในพจนานุกรมบริบทที่มีการแสดงผลแม่แบบในคำถาม ตอนนี้ในเทมเพลตนั้นเขียนบรรทัดนี้: ตอนนี้ในฟังก์ชั่นจาวาสคริปต์ของคุณก่อนที่จะทำการร้องขอ ajax เขียนสิ่งนี้: var csrf = $ ('# csrf') val () สิ่งนี้จะเลือกค่าของโทเค็นที่ส่งไปยังเทมเพลตและเก็บไว้ในตัวแปร csrf ตอนนี้ในขณะที่ทำการโทร ajax ในข้อมูลโพสต์ของคุณให้ส่งค่านี้เช่นกัน: "csrfmiddlewaretoken": csrf

สิ่งนี้จะใช้ได้แม้ว่าคุณจะไม่ได้ใช้แบบฟอร์ม django

อันที่จริงตรรกะตรงนี้คือ: คุณต้องใช้โทเค็นซึ่งคุณจะได้รับจากการร้องขอ ดังนั้นคุณต้องคิดฟังก์ชั่นที่ถูกเรียกใช้ทันทีหลังจากเข้าสู่ระบบเมื่อคุณมีโทเค็นนี้แล้วทำการโทร ajax อีกครั้งเพื่อรับมันหรือส่งต่อไปยังเทมเพลตที่ ajax ของคุณเข้าถึงได้


มีโครงสร้างไม่ดี แต่อธิบายได้ดี ปัญหาของฉันถูกฉันถูกส่ง CSRF ในลักษณะนี้มากกว่าcsrftoken: csrftoken csrfmiddlwaretoken: csrftokenหลังจากการเปลี่ยนแปลงมันใช้งานได้ ขอขอบคุณ
ผู้เริ่มต้นเกือบ

1

สำหรับบางคนที่เจอสิ่งนี้และพยายามแก้ไขปัญหา:

1) เช็ค django csrf (สมมติว่าคุณกำลังส่ง) อยู่ที่นี่

2) ในกรณีของฉันsettings.CSRF_HEADER_NAMEตั้งค่าเป็น 'HTTP_X_CSRFTOKEN' และการโทร AJAX ของฉันกำลังส่งส่วนหัวชื่อ 'HTTP_X_CSRF_TOKEN' เพื่อให้สิ่งต่าง ๆ ไม่ทำงาน ฉันสามารถเปลี่ยนได้ในการโทร AJAX หรือการตั้งค่า django

3) หากคุณเลือกที่จะเปลี่ยนฝั่งเซิร์ฟเวอร์ให้ค้นหาตำแหน่งการติดตั้งของ django และcsrf middlewareทำลายจุดพักใน. f ที่คุณกำลังใช้virtualenvงานมันจะเป็นดังนี้:~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py

import ipdb; ipdb.set_trace() # breakpoint!!
if request_csrf_token == "":
    # Fall back to X-CSRFToken, to make things easier for AJAX,
    # and possible for PUT/DELETE.
    request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')

จากนั้นตรวจสอบให้แน่ใจว่าcsrfโทเค็นนั้นมาจากคำขออย่างถูกต้องแล้ว

4) หากคุณจำเป็นต้องเปลี่ยนส่วนหัวของคุณ ฯลฯ - เปลี่ยนตัวแปรนั้นในไฟล์การตั้งค่าของคุณ



0

ในกรณีของฉันมีปัญหากับการกำหนดค่า nginx ที่ฉันได้คัดลอกจากเซิร์ฟเวอร์หลักไปยังเซิร์ฟเวอร์ชั่วคราวด้วยการปิดการใช้งาน https ที่ไม่จำเป็นในสองในกระบวนการ

ฉันต้องแสดงความคิดเห็นทั้งสองบรรทัดในการกำหนดค่าเพื่อให้มันทำงานอีกครั้ง:

# uwsgi_param             UWSGI_SCHEME    https;
# uwsgi_pass_header       X_FORWARDED_PROTO;

0

นี่เป็นวิธีแก้ปัญหาที่น้อยกว่าโดย Django:

<script type="text/javascript">
// using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
// set csrf header
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

// Ajax call here
$.ajax({
    url:"{% url 'members:saveAccount' %}",
    data: fd,
    processData: false,
    contentType: false,
    type: 'POST',
    success: function(data) {
        alert(data);
        }
    });
</script>

ที่มา: https://docs.djangoproject.com/en/1.11/ref/csrf/

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.