programing

장고의 AJAX를 통해 매개 변수를 게시하는 동안 "CSRF 토큰 누락 또는 부정확"

css3 2023. 9. 27. 18:07

장고의 AJAX를 통해 매개 변수를 게시하는 동안 "CSRF 토큰 누락 또는 부정확"

다음과 같은 매개 변수를 게시하려고 합니다.

 jQuery.ajax(
        {
            'type': 'POST',
            'url': url,
            'contentType': 'application/json',
            'data': "{content:'xxx'}",
            'dataType': 'json',
            'success': rateReviewResult 
        }
    );

로 .Forbidden 403. CSRF verification failed. Request aborted.사용중입니다'django.middleware.csrf.CsrfViewMiddleware'보안을 훼손하지 않으면서 이 문제를 예방할 수 있는 방법을 찾을 수 없었습니다

AJAX 포스트 요청은 두 가지 방법으로 할 수 있습니다.

  1. 보기에 crf 토큰을 확인하지 말라고 하는 것입니다.은 데코레이터다를 하여 할 수.@csrf_exempt과 같이:,:

    from django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt
    def your_view_name(request):
        ...
    
  2. 각 AJAX 요청에 crf 토큰을 내장하는 방법은 다음과 같습니다.

    $(function () {
        $.ajaxSetup({
            headers: { "X-CSRFToken": getCookie("csrftoken") }
        });
    });
    

    서. getCookie함수는 쿠키에서 crf 토큰을 검색합니다.저는 다음과 같은 구현을 사용합니다.

    function getCookie(c_name)
    {
        if (document.cookie.length > 0)
        {
            c_start = document.cookie.indexOf(c_name + "=");
            if (c_start != -1)
            {
                c_start = c_start + c_name.length + 1;
                c_end = document.cookie.indexOf(";", c_start);
                if (c_end == -1) c_end = document.cookie.length;
                return unescape(document.cookie.substring(c_start,c_end));
            }
        }
        return "";
     }
    

    또한 jQuery에는 쿠키에 액세스하기 위한 플러그인이 있습니다.

    // set cookie
    $.cookie('cookiename', 'cookievalue');
    // read cookie
    var myCookie = $.cookie('cookiename');
    // delete cookie
    $.cookie('cookiename', null);
    

가장 은 를 입니다.{{csrf_token}}데이터의 값:

jQuery.ajax(
    {
        'type': 'POST',
        'url': url,
        'contentType': 'application/json',
        'data': {
            'content': 'xxx',
            'csrfmiddlewaretoken': '{{ csrf_token }}',
        },
        'dataType': 'json',
        'success': rateReviewResult 
    }
);

다니엘이 올린 코드를 어떻게 해야 하는지 이해하는 데 시간이 좀 걸렸습니다.하지만 실제로 자바스크립트 파일의 처음에 붙여넣기만 하면 됩니다.

지금까지 가장 좋은 해결책은 다음과 같습니다.

  1. 만들기csrf.js을 대다

  2. 코드 붙여넣기csrf.js을 대다

  3. 필요한 템플릿의 코드 참조

    <script type="text/javascript" src="{{ STATIC_PREFIX }}js/csrf.js"></script>
    

하세요를 하세요.STATIC_PREFIX/js/csrf.js내 파일을 가리킵니다. 중입니다.STATIC_PREFIX 변수{% get_static_prefix as STATIC_PREFIX %}.


고급 팁: 템플릿을 사용하고 있고 다음과 같은 것이 있는 경우base.html여기서 확장하면 스크립트를 참조하기만 하면 되고 나머지 파일에서는 더 이상 걱정할 필요가 없습니다.제가 알기로는, 이것도 보안 문제를 나타내면 안 됩니다.

심플하고짧은

$.ajaxSetup({
  headers: { "X-CSRFToken": '{{csrf_token}}' }
});

오어

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

문서들

한 경우 만 X-CSRFToken는 ajax에 csrftoken. JQuery는 플러그인 없이(어떤 이유에서인지) 쿠키를 수행하지 않습니다.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>

그리고 최소한의 코드 변경은 다음과 같습니다.

$.ajax({
  headers: { "X-CSRFToken": $.cookie("csrftoken") },
  ...
});

js를 템플릿에 포함하지 않을 경우 플러그인이 없는 가장 빠른 솔루션은 다음과 같습니다.

.<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>에서 script.js합니다를 합니다.csrfmiddlewaretoken당신의 안으로data사전:

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

를와 간단합니다.data: {csrfmiddlewaretoken: '{{ csrf_token }}'}

어제도 같은 문제를 받았고 간단한 해결 방법이 있으면 사람들에게 도움이 될 것 같아서 jQuery.djangocsrf라는 jQuery 플러그인을 작성했습니다.모든 요청에 CSRF 토큰을 추가하는 대신 AjaxSend jQuery 이벤트에 자신을 후크하고 헤더에 클라이언트 쿠키를 추가합니다.

사용 방법은 다음과 같습니다.

1- 포함:

<script src="path/to/jquery.js"></script>
<script src="path/to/jquery.cookie.js"></script>
<script src="path/to/jquery.djangocsrf.js"></script>

2- 코드에서 활성화합니다.

$.djangocsrf( "enable" );

템플릿이 다음을 사용할 경우 항상 쿠키에 토큰을 추가합니다.{% csrf_token %}. 템플릿에서 특수 태그를 사용하지 않더라도 항상 추가하려면@ensure_csrf_cookie데코레이터:

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def my_view(request):
    return render(request, 'mytemplate.html')

참고: 장고 1.6.2를 사용하고 있습니다.

모든 답변에 감사드립니다.저는 장고 1.5.1을 사용하고 있습니다.파티에 좀 늦었지만, 이만 가보겠습니다.

장고 프로젝트에 대한 링크가 매우 유용하다는 것을 알았지만, 아약스에 전화를 걸 때마다 추가 자바스크립트 코드를 포함시킬 필요는 없었습니다.

jerrykan의 응답은 매우 간결하고, 그렇지 않으면 일반적인 Ajax call에 한 줄만 추가하기 때문에 좋습니다.장고 템플릿 태그를 사용할 수 없는 상황에 대한 그의 의견 아래에 있는 의견에 대해, DOM에서 crf 미들웨어 토큰을 로드하는 것은 어떨까요?

var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
jQuery.ajax({
    type: 'POST',
    url: url,
    data: { 'csrfmiddlewaretoken': token },
    dataType: 'json',
    success: function(data) { console.log('Yippee! ' + data); } 
});

편집 2016년 3월

지난 몇 년간 이 문제에 대한 저의 접근 방식이 바뀌었습니다.아래 코드(Django documents에서)를 main.js 파일에 추가하여 모든 페이지에 로드합니다.작업이 완료되면 ajax와의 CSRF 토큰에 대해 다시 걱정할 필요가 없습니다.

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;
}
var csrftoken = getCookie('csrftoken');

포함하다x-csrftoken요청한 헤더:

var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
jQuery.ajax({
    type: 'POST',
    url: url,
    beforeSend : function(jqXHR, settings) {
        jqXHR.setRequestHeader("x-csrftoken", get_the_csrf_token_from_cookie());
    },
    data: data,
    dataType: 'json',

});

다른 답변을 읽은 후에도 여전히 어려움을 겪고 있는 사람이 있다면 다음을 시도해 보십시오.

   $.ajax({
            type: "POST",
            beforeSend: function (request)
            {
                request.setRequestHeader("X-CSRF-TOKEN", "${_csrf.token}");
            },
            url: servlet_path,
            data : data,
            success : function(result) {
            console.log("Success!");
   }
});

이런 식으로 할 때는 그러지 말아 주세요.{% csrf_token %}내부에<form></form>tags. 그러면 여기 설명된 것처럼 javascript에 다음 코드를 추가합니다.

    function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            // 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;
    }
    const csrftoken = getCookie('csrftoken');

// using js fetch
// https://docs.djangoproject.com/en/3.1/ref/csrf/#setting-the-token-on-the-ajax-request
    const request = new Request(
    /* URL */,
    {headers: {'X-CSRFToken': csrftoken}}
);
fetch(request, {
    method: 'POST',
    mode: 'same-origin'  // Do not send CSRF token to another domain.
}).then(function(response) {
    // ...
});

여기에 두고 싶은 것은 만약GET사용 사례에서 작동합니다. 그러면 CSRF 토큰이 필요하지 않습니다.나의 사용 사례를 위해, 사용하기GET괜찮았습니다.

html

<form action="">
        {% csrf_token %}
    </form>

JS

 <script>   
     const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
              const request = new Request(
                   'url_here',
                  {headers: {'X-CSRFToken': csrftoken}}
              );
              fetch(request, {
                  method: 'POST',
                  // mode: 'same-origin' optinal // Do not send CSRF token to another domain.
              }).then(function(response) {
                  console.log(response);
              });
    
    </script>

자세한 내용은 참조 링크

내 실수에 대한 요약으로:

  1. 요청 내용 유형을 설정하는 것을 잊지 마십시오.
  2. crf 값을 가져옵니다.

    NB. 기본 쿠키 이름은csrftoken, 하지만 에 의해 압도될 수 있습니다. CSRF_COOKIE_NAME세팅

    • 쿠키에 액세스할 수 없는 경우 DOM(CSRF_USE_SSESS 또는 CSRF_COOKIE_HTTP ONLY를 True로 설정)

    문서.querySelector('[name= csrfmiddlewaretoken])" 값;

  3. 요청 헤더를 설정합니다. XMLHttpRequest를 사용하고 있습니다.
const Http = new XMLHttpRequest();
Http.setRequestHeader("X-CSRFToken", CSRF_VALUE);
Http.setRequestHeader("X_CSRFTOKEN", CSRF_VALUE);

헤더 이름은 다음과 같이 관리됩니다.CSRF_HEADER_NAME설정, 기본값은HTTP_X_CSRFTOKEN.

그러나: "서버에서 수신한 헤더 이름은 모든 문자를 대문자로 변환하고 하이픈을 밑줄로 바꾸고 이름에 'HTTP_' 접두사를 추가하여 정규화됩니다." src.

그래서 만약에 설정을 해주시면.HTTP_X_CSRFTOKEN헤더, 장고는 그것을 다음으로 변환할 것입니다.HTTP_HTTP_X_CSRFTOKEN입니다를 입니다.CSRF missed오류를 범실.

Http.setRequestHeader("X-CSRFToken", csrftoken);        // This worked
Http.setRequestHeader("X-CSRFTOKEN", csrftoken);        // Also this
Http.setRequestHeader("HTTP-X-CSRFToken", csrftoken);   // Not working
Http.setRequestHeader("HTTP_X_CSRFTOKEN", csrftoken);   // Not Working
Http.setRequestHeader("X_CSRFTOKEN", csrftoken);        // Not working !!
  1. 에서 브라우저 url url 의 ajax와 않음127.0.0.1&localhost똑같지 않아요!!

  2. data.append("csrfmiddlewaretoken", csrftoken);제가 알기로는 요청서에.

언급URL : https://stackoverflow.com/questions/6506897/csrf-token-missing-or-incorrect-while-post-parameter-via-ajax-in-django