Cookie Django CSRF no configurada

85

Tengo algún problema por un tiempo, estoy experimentando que la cookie CSRF no está configurada. Mire los códigos a continuación

Pitón

def deposit(request,account_num):
if request.method == 'POST':
    account = get_object_or_404(account_info,acct_number=account_num)
    form_=AccountForm(request.POST or None, instance=account)
    form = BalanceForm(request.POST)
    info = str(account_info.objects.filter(acct_number=account_num))
    inf=info.split()
    if form.is_valid():
    #cd=form.cleaned_data
        now = datetime.datetime.now()
        cmodel = form.save()
        cmodel.acct_number=account_num
        #RepresentsInt(cmodel.acct_number)
        cmodel.bal_change="%0.2f" % float(cmodel.bal_change)
        cmodel.total_balance="%0.2f" %(float(inf[1]) + float(cmodel.bal_change))
        account.balance="%0.2f" % float(cmodel.total_balance)
        cmodel.total_balance="%0.2f" % float(cmodel.total_balance)
        #cmodel.bal_change=cmodel.bal_change
        cmodel.issued=now.strftime("%m/%d/%y %I:%M:%S %p")
        account.recent_change=cmodel.issued
        cmodel.save()
        account.save()
        return HttpResponseRedirect("/history/" + account_num + "/")
    else:
        return render_to_response('history.html',
                          {'account_form': form},
                          context_instance=RequestContext(request))

En el HTML aquí está el código

HTML

<form action="/deposit/{{ account_num }}/" method="post">

<table>
<tr>
{{ account_form.bal_change }}
&nbsp;
<input type="submit" value="Deposit" />
</tr>
{% csrf_token %}
</table>
</form>

Estoy atascado, ya borré la cookie, usé otro navegador pero aún no configuré la cookie csrf.


fuente
¿Tienes CsrfViewMiddlewareen tu MIDDLEWARE_CLASSESentorno?
alecxe
Agregue {%csrf_token%}su formulario en la plantilla.
Rohan
4
@Rohan ya está ahí, mira la pregunta.
alecxe
1
Sí, ya tengo CsrfViewMiddleware, y ya tengo el csrf_token en mi formulario
He estado usando el módulo cors de Django y accedo a él a través de ReactJS. (Ambos estaban en localhost). También tuve este problema del OP. Descubrí que agregar credentials: 'include'a la solicitud POST y luego TAMBIÉN agregar en django's settings.py: CORS_ALLOW_CREDENTIALS = Trueparece haber solucionado el problema sin la necesidad de agregar @csrf_exempta la vista. En realidad, está en los documentos ... pypi.org/project/django-cors-headers-multi * Sé que esto se relaciona con una de las preguntas anteriores, pero aún no puedo comentar y espero salvar a alguien más el tiempo me llevó a encontrar t
DW

Respuestas:

133

Esto también puede ocurrir si CSRF_COOKIE_SECURE = Trueestá configurado y está accediendo al sitio de forma no segura o si CSRF_COOKIE_HTTPONLY = Trueestá configurado como se indica aquí y aquí

Druska
fuente
10
¡Gracias! Lo mismo vale SESSION_COOKIE_SECURE = True.
NonameSL
74
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt 
def your_view(request):
    if request.method == "POST":
        # do something
    return HttpResponse("Your response")
Евгений Смирнов
fuente
60
Deshabilitar el mecanismo de seguridad por completo no es una buena forma de corregir el error.
Guillaume Algis
2
Si está utilizando cookiecutter-django en 2017, esta es la respuesta correcta en producción.
André Duarte
1
¿Por qué es eso, por curiosidad?
Patrick Gallagher
3
Esta respuesta no sugiere "deshabilitar el mecanismo de seguridad por completo", solo indica cómo hacerlo para un caso único en el que es posible que no pueda usar el token CSRF. Este es mi caso, donde necesito ofrecer una acción POST a un cliente externo.
mariotomo
Este es un tipo de elemento TODO que uso durante la fase de desarrollo, cuando no puedes proporcionar el token csrf desde la interfaz de usuario. Pero ciertamente no se recomienda para una aplicación en vivo.
Aman Madan
24

Si está utilizando la API de HTML5 Fetch para realizar solicitudes POST como un usuario que ha iniciado sesión y obteniendo Forbidden (CSRF cookie not set.), podría deberse a que, de forma predeterminada fetch, no incluye cookies de sesión, lo que hace que Django piense que usted es un usuario diferente al que cargó la página. .

Puede incluir el token de sesión pasando la opción credentials: 'include'para recuperar:

var csrftoken = getCookie('csrftoken');
var headers = new Headers();
headers.append('X-CSRFToken', csrftoken);
fetch('/api/upload', {
    method: 'POST',
    body: payload,
    headers: headers,
    credentials: 'include'
})
usuario85461
fuente
¿Puedo saber cuál es el método Header () que instanciaste? es ese método global de JavaScript?
Abz Rockers
@AbzRockers: Sí, Headerses una interfaz javascript global, parte de la API de recuperación de HTML5. developer.mozilla.org/en-US/docs/Web/API/Headers
user85461
13

A partir de esto, puede resolverlo agregando el decorador secure_csrf_cookie a su vista

from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def yourView(request):
 #...

si este método no funciona. intentará comentar csrf en middleware. y prueba de nuevo.

dscanon
fuente
5

Me encontré con una situación similar mientras trabajaba con DRF, la solución fue agregar el método .as_view () a la Vista en urls.py

Pratik Mhatre
fuente
Sería mejor si incluyeras también algún código
Alex Jolig
1
@AlexJolig acaba de enfrentar el mismo problema, el problema fue que olvidé agregar .as_view()después de mi ApiView. Así se veía el código: urlpatterns += path('resource', ResourceView)Y así debería ser: urlpatterns += path('resource', ResourceView.as_view())
Alveona
4

Si está utilizando DRF, compruebe si sus patrones de URL son correctos, tal vez se le olvidó .as_view():

Así que cómo se veía el código mío:

urlpatterns += path('resource', ResourceView) 

Y así debería gustarle:

urlpatterns += path('resource', ResourceView.as_view())
Alveona
fuente
1

intente verificar si lo ha instalado en settings.py

 MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',)

En la plantilla, los datos están formateados con el csrf_token:

<form>{% csrf_token %}
</form>
drabo2005
fuente
No tengo todo su código, pero creo que el asunto está aquí: def deposit (request, account_num): lo cambié a def deposit (request): y encuentre una manera de devolver la llamada al account_num. ahora dependerá de si account_num es un campo de tabla o una variable.
drabo2005
Es una variable {{account_num}}, pero ¿cómo afecta esto al token csrf?
Creo que el token csrf se refería solo a la solicitud, por lo que no puede verificar ni manejar lo que sucede con la variable aquí. compruebe el djangoproject.com puede ser que pueda obtener una respuesta adecuada sobre el csrf_token.
drabo2005
1

Esto también ocurre cuando no configura la acción del formulario.
Para mí, mostraba este error cuando el código era:

<form class="navbar-form form-inline my-2 my-lg-0" role="search" method="post">

Cuando corrigí mi código en esto:

<form class="navbar-form form-inline my-2 my-lg-0" action="{% url 'someurl' %}" role="search" method="post">

mi error desapareció.

Gokul Yesudoss
fuente
0

El problema parece que no está manejando las GETsolicitudes de manera adecuada o publicando directamente los datos sin obtener primero el formulario.

Cuando acceda por primera vez a la página, el cliente enviará una GETsolicitud, en ese caso debe enviar html con el formulario correspondiente.

Posteriormente, el usuario completa el formulario y envía la POSTsolicitud con los datos del formulario.

Tu vista debería ser:

def deposit(request,account_num):
   if request.method == 'POST':
      form_=AccountForm(request.POST or None, instance=account)
      if form.is_valid(): 
          #handle form data
          return HttpResponseRedirect("/history/" + account_num + "/")
      else:
         #handle when form not valid
    else:
       #handle when request is GET (or not POST)
       form_=AccountForm(instance=account)

    return render_to_response('history.html',
                          {'account_form': form},
                          context_instance=RequestContext(request))
Rohan
fuente
0

Compruebe que las cookies de Chrome estén configuradas con la opción predeterminada para sitios web. Permitir que los datos locales que se establezcan (recomendado).

IWS
fuente
0

Método 1:

from django.shortcuts import render_to_response
return render_to_response(
    'history.html',
    RequestContext(request, {
        'account_form': form,
    })

Método 2:

from django.shortcuts import render
return render(request, 'history.html', {
    'account_form': form,
})

Porque el método render_to_response puede generar algún problema con las cookies de respuesta.

shenqi0920
fuente
0

Me acabo de ver una vez, la solución es vaciar las cookies. Y se puede cambiar durante la depuración relacionada con SECRET_KEY.

JunLe Meng
fuente
0

Limpiar la memoria caché de mi navegador solucionó este problema. Había estado cambiando entre entornos de desarrollo local para hacer el tutorial django-blog-zinnia después de trabajar en otro proyecto cuando sucedió. Al principio, pensé que cambiar el orden de INSTALLED_APPS para que coincidiera con el tutorial lo había causado, pero los volví a colocar y no pude corregirlo hasta que borré el caché.

infosmith
fuente
0

Estaba usando Django 1.10 antes, así que estaba enfrentando este problema. Ahora lo bajé a Django 1.9 y está funcionando bien.

indspecter
fuente
Usando 1.10.3 tuve este problema. La actualización a 1.10.6 me solucionó el problema.
Mike Darmetko
0

Tuve el mismo error, en mi caso, agregar method_decorator ayuda:

from django.views.decorators.csrf import csrf_protect
from django.utils.decorators import method_decorator

method_decorator(csrf_protect)
def post(self, request):
    ...
moszoro
fuente
0

Asegúrese de que el backend de su sesión de django esté configurado correctamente en settings.py. Entonces prueba esto

class CustomMiddleware(object):
  def process_request(self,request:HttpRequest):
      get_token(request)

Añadir este middleware en settings.pyvirtud de MIDDLEWARE_CLASSESo MIDDLEWAREen función de la versión de Django

get_token: devuelve el token CSRF necesario para un formulario POST. El token es un valor alfanumérico. Se crea un nuevo token si aún no se ha establecido uno.

arp
fuente
-4

En su opinión, ¿está utilizando el decorador csrf?

from django.views.decorators.csrf import csrf_protect

@csrf_protect def view(request, params): ....

abhishekgarg
fuente