Codong's Development Diary RSS 태그 관리 글쓰기 방명록
CSRF (1)
2021-03-20 21:54:25

😄 개요


간만에 장고로 다시 개인적인 toy project를 해보고 싶어서, 장고 프로젝트 생성하고 간단하게 POST 요청 비동기통신을 이용해보고 싶어서 jquery의 ajax를 사용했다. 역시, ERROR가 안뜰리 없다.


😱 문제점


우선 작성한 코드는 아주 간단했다.

$.ajax({
      type:'POST',
      url:'/search',
      data:JSON.stringify(geodata),
      success:function(json){
          console.log("to view data pass success",json);

      },
      error : function(xhr,errmsg,err) {
      console.log(xhr.status + ": " + xhr.responseText); 
      }
      });

search 로 POST 요청을 보냈는데.......?

Forbidden (CSRF cookie not set.): /search
[20/Mar/2021 10:47:16] "POST /search HTTP/1.1" 403 2864

결과는 처참했다....☠️☠️☠️☠️☠️

간단하게 요약하자면 django의 CSRF(Cross Site Request Forgery 사이트 간 요청 위조) 보안 정책으로 인해 일어난 에러이다.


👍 해결법


1️⃣ decorator를 사용하여 특정 view에 csrf 적용하지 않기

단순하게 csrf 정책을 사용하지 않는 것이다. 방법은 아주 간단하다. views.py에 원하는 view에 decorator를 달아주면 된다.

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def search(request):

    return HttpResponse('success')

이렇게 하면 해결되지만, 뭔가 보안상 뭔가 찜찜하다.. 그래서 다음 방법을 준비했다❗️


2️⃣ html 파일 header부분에 csrf token 생성하기

이 방법은 django 공식 문서(보러가기)에 있는 방법이다. ajax를 사용하는 html 파일의 header 부분에 아래 코드를 작성하면 된다.

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

  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", csrftoken);
          }
      }
  });
</script>

대강 보면 토큰을 만들고 ajax에 미리 설정해주는 것 같다. 필요한 사항은 당연히 jquery를 먼저 불러와야 한다.


➕ 2021/04/08 내용 추가

후에 위의 방법으로도 됐다가 안 됐다가 하다가 결국 또 안되길래 간단한 다른 방법을 찾았다.

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

단순히 이 부분만 html 파일의 header 부분에 추가해주면된다... 이것 때문에 시간 또 날린거 너무 화나네🤬


😂 마무리


처음 배울 때에는 어떤 것인지도 모르고 단순히 에러만 없애려고 사용했었는데, 다시 보니 감회가 새롭고 오히려 더 기억에 남게 되었던 것 같다. 하지만 내 머리를 너무 믿지 말자. 오늘도 포스팅... 포스팅...🧑‍💻


reference

'python > django' 카테고리의 다른 글

[django] mysql + docker-compose  (1) 2022.12.25
[django] ajax를 이용해서 데이터 주고받기  (0) 2021.03.20