【问题标题】:detail: "CSRF Failed: CSRF token missing or incorrect."详细信息:“CSRF 失败:CSRF 令牌丢失或不正确。”
【发布时间】:2016-12-31 20:06:36
【问题描述】:

我在 restaurant_detail.html 中的 script 标签内使用了 window.CSRF_TOKEN = "{{ csrf_token }}" ,其中呈现了我用于发布评论的反应页面。不过,我遇到了一个错误。在我的 onSubmit 函数中,我安慰检查是否通过了 csrf 令牌,是的。

我发表评论的 axios 代码是

onSubmit(props){
        console.log('csrf',CSRF_TOKEN);
        axios({
            method:'POST',
            url:'/api/review/create/',
            headers:{
                'X-CSRF-Token':CSRF_TOKEN,
                //'Access-Control-Allow-Origin':'*',
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            },
            data:{
                review:props.review
            }
        })
        .then(response => {
            console.log('success');
        })
        .catch(error => {
            throw("Error: ",error);
        });
    } 

api/Views.py

class ReviewCreateAPIView(CreateAPIView):
    queryset = Review.objects.all()
    # permisssion_classes = [IsAuthenticated]

    def get_serializer_class(self):
        model_type = self.request.GET.get('type')
        slug = self.request.GET.get('slug')
        parent_id = self.request.GET.get('parent_id')
        return create_review_serializer(model_type=model_type, slug=slug, parent_id=parent_id, reviewer=self.request.user)

serializers.py

def create_review_serializer(model_type='restaurant',slug=None, parent_id=None, reviewer=None):
    class ReviewCreateSerializer(ModelSerializer):
        class Meta:
            model = Review 
            fields = ('id','review','created',)

        def __init__(self, *args, **kwargs):
            self.model_type = model_type
            self.slug = slug 
            self.parent_obj = None 
            if parent_id:
                parent_qs = Review.objects.filter(id=parent_id)
                if parent_qs.exists() and parent_qs.count() == 1:
                    self.parent_obj = parent_qs.first()
            return super(ReviewCreateSerializer, self).__init__(*args, **kwargs)

        def validate(self, data):
            model_type = self.model_type
            model_qs = ContentType.objects.filter(model=model_type)
            if not model_qs.exists() or model_qs.count() != 1:
                raise ValidationError('This is not a valid content type')
            SomeModel = model_qs.first().model_class()
            obj_qs = SomeModel.objects.filter(slug=self.slug) # Restaurant.objects.filter(slug=self.slug)
            if not obj_qs.exists() or obj_qs.count() != 1:
                raise ValidationError('This is not a slug for this content type')
            return data 

        def create(self, validated_data):
            review = validated_data.get('review')
            print('review',review)
            if reviewer:
                main_reviewer = reviewer
            else:
                main_reviewer = User.objects.all().first()
            model_type = self.model_type
            slug = self.slug 
            parent_obj = self.parent_obj
            review = Review.objects.create_for_model_type(model_type, slug, review, main_reviewer, parent_obj=parent_obj)
            return review

    return ReviewCreateSerializer

urls.py

url(r'^create/$', ReviewCreateAPIView.as_view(), name="reviewcreateapiview"),

restaurant_detail.html

<div id="app"></div>
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>

我该如何解决这个问题?

【问题讨论】:

    标签: javascript django reactjs django-rest-framework axios


    【解决方案1】:

    我不熟悉 axios,但我用 JQuery 解决了一个类似的问题:

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

    【讨论】:

      【解决方案2】:

      您必须在 ajax 调用中使用 cookie 值设置标头。

      $.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'));
           }
       } 
      });
      

      【讨论】:

      • 但我正在使用 axios。我必须对 axios 做同样的事情吗?
      【解决方案3】:

      你犯了一个简单的错误。有一个错字。替换

      'X-CSRF-Token'

      'X-CSRFToken'

      如果您的代码正确,那么它应该发布您的数据。

      【讨论】:

      • 哦,是的!它真的解决了这个问题。感谢您的回答。
      猜你喜欢
      • 2014-12-25
      • 2014-02-26
      • 2021-10-01
      • 2020-09-19
      • 2017-01-29
      • 1970-01-01
      • 2021-07-14
      • 2012-05-16
      • 2020-01-17
      相关资源
      最近更新 更多