2012-05-19 33 views
11

Tôi đã đọc Django - CSRF verification failed và một số câu hỏi (và câu trả lời) liên quan đến phương thức django và POST. Một trong những best-nhưng-không-làm việc-cho-tôi trả lời là https://stackoverflow.com/a/4707639/755319Phương thức POST luôn trả về 403 Forbidden

Tất cả các câu trả lời chấp thuận đề nghị ít nhất 3 điều:

  1. Sử dụng RequestContext như tham số thứ ba của render_to_response_call
  2. Add {% csrf_token%} trong mọi hình thức với phương thức POST
  3. Kiểm tra MIDDLEWARE_CLASSES trong settings.py

tôi đã thực hiện đúng như đề nghị, nhưng lỗi vẫn xuất hiện. Tôi sử dụng django 1.3.1 (từ ubuntu 12.04 kho) và python 2.7 (mặc định từ ubuntu)

này Xem của tôi:

# Create your views here. 
from django.template import RequestContext 
from django.http import HttpResponse 
from django.shortcuts import render_to_response 
from models import BookModel 

def index(request): 
    return HttpResponse('Welcome to the library') 

def search_form(request): 
    return render_to_response('library/search_form.html') 

def search(request): 
    if request.method=='POST': 
     if 'q' in request.POST: 
      q=request.POST['q'] 
      bookModel = BookModel.objects.filter(title__icontains=q) 
      result = {'books' : bookModel,} 
      return render_to_response('library/search.html', result, context_instance=RequestContext(request)) 
     else: 
      return search_form(request) 
    else: 
     return search_form(request) 

và đây là mẫu của tôi (search_form.html):

{% extends "base.html" %} 
{% block content %} 
<form action="/library/search/" method="post"> 
    {% csrf_token %} 
    <input type="text" name="q"> 
    <input type="submit" value="Search"> 
</form> 
{% endblock %} 

Tôi đã khởi động lại máy chủ, nhưng lỗi 403 bị cấm vẫn còn đó, cho biết xác minh CSRF không thành công.

Tôi đã 2 câu hỏi:

  1. Làm thế nào để khắc phục lỗi này?
  2. Tại sao rất khó để tạo một "POST" trong django, ý tôi là có lý do cụ thể nào để làm cho nó quá chi tiết (tôi đến từ PHP và chưa bao giờ tìm thấy vấn đề như vậy trước đây)?

Trả lời

3

Hãy thử đặt RequestContext trong render_to_response quan điểm search_form của:

context_instance=RequestContext(request) 
+0

Đó của công trình, cảm ơn bạn đã trả lời của bạn. Nhưng làm thế nào và tại sao? Bạn có thể xin giải thích? – goFrendiAsgard

+2

https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#how-to-use-it - đọc điểm # 3 – zubinmehta

+2

Bởi vì 'csrf_token' phải được tạo trong chế độ xem của bạn để django có thể vượt qua nó vào mẫu. Trong trường hợp của bạn, vì chế độ xem tìm kiếm của bạn không tạo mã thông báo, '{% csrf_token%}' trong mẫu của bạn là 'chuỗi rỗng (Không)' và trang kết quả không thành công trên xác minh – FallenAngel

0

Bạn cũng có thể sử dụng

direct_to_template(request, 'library/search.html', result) 

thay vì

render_to_response('library/search.html', result, context_instance=RequestContext(request)) 

direct_to_template thêm RequestContext aut omatically. Nhưng lưu ý rằng direct_to_template sẽ không được dùng nữa và thay vào đó, django sẽ sử dụng CBV TemplateView.

RequestContext cho phép bạn sử dụng bộ xử lý ngữ cảnh. Và đây là sai lầm của bạn: {% csrf_token %} xuất chuỗi rỗng và bạn nhận được 403.

+0

Xin chào, cảm ơn bạn cho bình luận của bạn, có vẻ như tôi nên xem xét rất nhiều điều trước khi trở nên quen thuộc với django: D – goFrendiAsgard

5

Cách dễ nhất để tránh các vấn đề như vậy là sử dụng lối tắt render.

from django.shortcuts import render 
# .. your other imports 

def search_form(request): 
    return render(request, 'library/search_form.html') 

def search(request): 
    q = request.GET.get('q') 
    results = BookModel.objects.all() 
    if q: 
     results = results.filter(title__icontains=q) 
    return render(request, 'library/search.html', {'result': results}) 
+0

+1 cho 'django.me' – San4ez

+0

Phải cố gắng này sớm, có vẻ rất rõ ràng, cảm ơn bạn đã trả lời của bạn. Có bất kỳ khuyết điểm nào khi sử dụng phương pháp này không? Tôi tự hỏi tại sao tài liệu và djangobook cung cấp cú pháp chi tiết như vậy nếu có cú pháp rõ ràng như vậy – goFrendiAsgard

+0

Tôi biết đây là một chuỗi cũ, nhưng tôi đã cập nhật nó để làm rõ thêm phương pháp tìm kiếm. Hy vọng rằng điều này bây giờ (hữu ích hơn). –

9

Tôi có thể sai tuy nhiên tôi thấy các giải pháp trên khá phức tạp.

những gì làm việc cho tôi chỉ đơn giản là bao gồm mã thông báo csrf của tôi vào yêu cầu đăng bài của tôi.

$.ajax({ 
    type: "POST", 
    url: "/reports/", 
    data: { csrfmiddlewaretoken: "{{ csrf_token }}", // < here 
      state:"inactive" 
      }, 
    success: function() { 
     alert("pocohuntus") 
     console.log("prototype") 
    } 
}) 
+2

Làm việc cho tôi - cảm ơn! – skaz

0

Bạn cần phải sử dụng RequestContext với trả lời của bạn

ví dụ trong view.py tập tin

from django.template import RequestContext 

def home(request): 
    return render_to_response('home.html',RequestContext(request, {})) 
2

Câu trả lời là 403 bcoz, django đòi hỏi một CSRF token (bao gồm trong bài dữ liệu) trong mọi yêu cầu POST mà bạn thực hiện.

Có rất nhiều cách để làm điều này như:

Thu token từ cookie và phương pháp đã được giải thích trong bài viết enter link description here

hoặc

Bạn có thể truy cập nó từ DOM sử dụng {{ csrf_token}}, có sẵn trong mẫu

Vì vậy, bây giờ sử dụng phương pháp thứ hai:

var post_data = { 
    ... 
    'csrfmiddlewaretoken':"{{ csrf_token }}" 
    ... 
} 
$.ajax({ 
    url:'url', 
    type:'POST' 
    data:post_data, 
    success:function(data){ 
    console.log(data); 
    }, 
    error:function(error){ 
    console.log(error); 
    } 
}); 
1

Câu trả lời này dành cho những người có thể gặp phải vấn đề tương tự này trong tương lai.

Thẻ mẫu CSRF {{csrf_token}} là bắt buộc đối với biểu mẫu ở Django ngăn chống lại Trang web yêu cầu trang web chéo. CSRF làm cho nó có thể cho một trang web độc hại đã được trình duyệt của khách hàng truy cập để thực hiện yêu cầu đến máy chủ của riêng bạn. Do đó các csrf_token được cung cấp bởi django làm cho nó đơn giản cho máy chủ django và trang web của bạn để được bảo vệ chống lại loại tấn công nguy hiểm. Nếu biểu mẫu của bạn không được bảo vệ bởi csrf_token, django trả về một trang bị cấm 403. Đây là một hình thức bảo vệ cho trang web của bạn đặc biệt là khi mã thông báo không được bỏ qua một cách có chủ ý.

Nhưng có những trường hợp mà trang web django không muốn bảo vệ biểu mẫu bằng cách sử dụng csrf_token. Ví dụ, tôi đã phát triển một ứng dụng USSD và một chức năng xem được yêu cầu để nhận được một yêu cầu POST từ API USSD. Chúng ta nên lưu ý rằng yêu cầu POST không phải từ một biểu mẫu trên máy khách do đó rủi ro của CSRF là không thể, vì một trang web độc hại không thể gửi yêu cầu. Yêu cầu POST được nhận khi người dùng quay mã USSD chứ không phải khi biểu mẫu được gửi.

Nói cách khác, có những tình huống mà chức năng sẽ cần nhận yêu cầu POST và sẽ không cần {{csrf_token}}.

Django cung cấp cho chúng tôi một trang trí @csrf_exempt. Trang trí này đánh dấu một cái nhìn như được miễn khỏi sự bảo vệ được đảm bảo bởi phần mềm trung gian.

from django.views.decorators.csrf import csrf_exempt 
from django.http import HttpResponse 

@csrf_exempt 
def my_view(request): 
    return HttpResponse('Hello world') 

Django cũng cung cấp một trình trang trí khác thực hiện cùng chức năng với {{csrf_token}}, nhưng không từ chối yêu cầu gửi đến. Người trang trí này là @requires_csrf_token. Ví dụ:

@requires_csrf_token 
def my_view(request): 
    c = {} 
    # ... 
    return render(request, "a_template.html", c) 

Các trang trí cuối cùng sẽ được đề cập trong bài này không chính xác những điều tương tự như {{csrf_token}} và nó được gọi @csrf_protect. Tuy nhiên, việc sử dụng trang trí này của chính nó không phải là thực hành tốt nhất bởi vì bạn có thể quên thêm nó vào quan điểm của bạn.Ví dụ:

@csrf_protect 
def my_view(request): 
    c = {} 
    # ... 
    return render(request, "a_template.html", c) 

Dưới đây là một số liên kết sẽ hướng dẫn và giải thích tốt hơn.

https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#module-django.views.decorators.csrf

https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/

http://www.squarefree.com/securitytips/web-developers.html#CSRF

Các vấn đề liên quan