2012-04-30 80 views
9

Tôi cố gắng xây dựng một trang web rất đơn giản, nơi người ta có thể thêm dữ liệu vào cơ sở dữ liệu sqlite3. Tôi có một biểu mẫu POST với hai kiểu nhập văn bản.Xác minh CSRF không thành công. Yêu cầu hủy bỏ

index.html:

{% if top_list %} 
    <ul> 
    <b><pre>Name Total steps</pre></b> 
    {% for t in top_list %} 
     <pre>{{t.name}} {{t.total_steps}}</pre> 
    {% endfor %} 
    </ul> 
    {% else %} 
    <p>No data available.</p> 
{% endif %} 
<br> 
<form action="/steps_count/" method="post"> 
    {% csrf_token %} 
    Name: <input type="text" name="Name" /><br /> 
    Steps: <input type="text" name="Steps" /><br /> 
    <input type="submit" value="Add" /> 
</form> 

forms.py:

from django import forms 
from steps_count.models import Top_List 

class Top_List_Form(forms.ModelForm): 
    class Meta: 
     model=Top_List 

views.py:

# Create your views here. 
from django.template import Context, loader 
from django.http import HttpResponse 
from steps_count.models import Top_List 
from steps_count.forms import Top_List_Form 
from django.template import RequestContext 
from django.shortcuts import get_object_or_404, render_to_response 

def index(request): 

if request.method == 'POST': 
    #form = Top_List_Form(request.POST) 
    print "Do something" 
else: 
    top_list = Top_List.objects.all().order_by('total_steps').reverse() 
    t = loader.get_template('steps_count/index.html') 
    c = Context({'top_list': top_list,}) 
    #output = ''.join([(t.name+'\t'+str(t.total_steps)+'\n') for t in top_list]) 
    return HttpResponse(t.render(c)) 

Tuy nhiên, khi tôi nhấp vào "submit" nút, tôi nhận được lỗi 403:

CSRF verification failed. Request aborted. 

Tôi đã bao gồm {% csrf_token %} trong index.html. Tuy nhiên, nếu nó là một vấn đề RequestContext, tôi thực sự không có ý tưởng về nơi và làm thế nào để sử dụng nó. Tôi muốn mọi thứ xảy ra trên cùng một trang (index.html).

Trả lời

13

Sử dụng render shortcut tự động thêm RequestContext.

from django.http import HttpResponse 
from django.shortcuts import get_object_or_404, render 
from steps_count.models import Top_List 
from steps_count.forms import Top_List_Form 


def index(request): 

    if request.method == 'POST': 
     #form = Top_List_Form(request.POST) 
     return HttpResponse("Do something") # methods must return HttpResponse 
    else: 
     top_list = Top_List.objects.all().order_by('total_steps').reverse() 
     #output = ''.join([(t.name+'\t'+str(t.total_steps)+'\n') for t in top_list]) 
     return render(request,'steps_count/index.html',{'top_list': top_list}) 
+0

Cảm ơn bạn rất nhiều, nó hoạt động! – Bebe

1

Bạn nên sử dụng

from django.shortcuts import render_to_response 
. 
. 
. 
return render_to_response("steps_count/index.html", {'top_list': top_list}, context_instance=RequestContext(request)) 

thay vì

return HttpResponse(t.render(c)) 

đọc về "xử lý ngữ cảnh" và xem this liên kết để biết chi tiết về cách bảo vệ CSRF làm việc trong Django.

CẬP NHẬT

tôi misread HttpResponse như render_to_response. Tôi đã cập nhật câu trả lời trước đây của mình.

1

Một lỗi phổ biến ở đây là sử dụng render_to_response (điều này thường được sử dụng trong các hướng dẫn cũ), không tự động bao gồm RequestContext. Render tự động bao gồm nó.

Tìm hiểu điều này khi tạo ứng dụng mới trong khi làm theo hướng dẫn và CSRF không hoạt động cho các trang trong ứng dụng mới.

4

Khi bạn tìm thấy loại thư này, có nghĩa là mã thông báo CSRF bị thiếu hoặc không chính xác. Vì vậy, bạn có hai lựa chọn.

  1. Đối với hình thức POST, bạn cần phải đảm bảo:

    • Trình duyệt của bạn được chấp nhận cookie.

    • Trong mẫu, có thẻ mẫu {% csrf_token%} bên trong mỗi biểu mẫu POST nhắm mục tiêu URL nội bộ.

  2. Cách đơn giản khác chỉ là nhận xét một dòng (KHÔNG NÊN) ('django.middleware.csrf.CsrfViewMiddleware') trong MIDDLEWARE_CLASSES từ tab thiết lập.

    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware', 
        'django.middleware.common.CommonMiddleware', 
        # 'django.middleware.csrf.CsrfViewMiddleware', 
        'django.contrib.auth.middleware.AuthenticationMiddleware', 
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 
        'django.contrib.messages.middleware.MessageMiddleware', 
        'django.middleware.clickjacking.XFrameOptionsMiddleware', 
    

    )

+0

Cảm ơn phần thứ hai. Tôi chỉ đơn giản là không cần điều đó! :) – SaurabhJinturkar

+0

Tắt CSRF là * KHÔNG * một giải pháp. Làm ơn đừng làm thế. (phần 2 của câu trả lời) – elnygren

0
function yourFunctionName(data_1,data_2){ 
     context = {} 
     context['id'] = data_1 
     context['Valid'] = data_2 
     $.ajax({ 
      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]); 
            if (cookie.substring(0, name.length + 1) == (name + '=')) { 
             cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 
             break; 
            } 
           } 
          } 
          return cookieValue; 
         } 
         if (settings.url == "your-url") 
          xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); 
        }, 

      url: "your-url", 
      type: "POST", 
      data: JSON.stringify(context), 
      dataType: 'json', 
      contentType: 'application/json' 
     }).done(function(data) { 
    }); 
+0

Bạn nên viết ajax của bạn như thế. –

0
if you put {%csrf_token%} and still you have the same issue, please try to change your angular version. because its works for me. initially i faced this issue while using angular 1.4.x version . after i degrade it into angular 1.2.8, my problem was fixed. 
and dont forgot to add angular-cookies.js and put this on your js file. 
if you using post request. 
"app.run(function($http, $cookies) { 
    console.log($cookies.csrftoken) 
    $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken; 
}); 
" 
0

Trong tiêu đề HTML của bạn, thêm

<meta name="csrf_token" content="{{ csrf_token }}"> 

Sau đó, trong JS của bạn/config góc:

app.config(function($httpProvider){ 
    $httpProvider.defaults.headers.post['X-CSRFToken'] = $('meta[name=csrf_token]').attr('content'); 
} 
1

Bạn có thể đã bỏ lỡ thêm dòng sau vào hình của bạn:

{% csrf_token %} 
Các vấn đề liên quan