Cookie do Django CSRF não definido

86

Eu tenho alguns problemas por um tempo agora, estou enfrentando CSRF Cookie not set. Por favor, olhe os códigos abaixo

Pitão

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))

No HTML aqui está o 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>

Estou preso, já limpei o cookie, usei outro navegador, mas ainda o cookie csrf não foi definido.

rhoitjadhav
fonte
Você tem CsrfViewMiddlewareem sua MIDDLEWARE_CLASSESconfiguração?
alecxe
Adicione {%csrf_token%}em seu formulário no modelo.
Rohan
4
@Rohan já está aí, veja a pergunta.
alecxe
1
Sim, eu já tenho CsrfViewMiddleware e já tenho o csrf_token em meu formulário
Estou usando o módulo Django cors e acessando-o através do ReactJS. (Ambos estavam no localhost). Eu também tive esse problema do OP. Eu descobri para mim que adicionar credentials: 'include'à solicitação POST e, em seguida, TAMBÉM adicionar no settings.py: do django CORS_ALLOW_CREDENTIALS = Trueparece ter corrigido o problema sem a necessidade de adicionar @csrf_exemptà visualização. Na verdade, está nos documentos ... pypi.org/project/django-cors-headers-multi * Eu sei que isso se relaciona a uma das perguntas acima, mas não posso comentar ainda e espero poupar o tempo de outra pessoa me levou para encontrar t
DW

Respostas:

134

Isso também pode ocorrer se CSRF_COOKIE_SECURE = Trueestiver definido e você estiver acessando o site de forma não segura ou se CSRF_COOKIE_HTTPONLY = Trueestiver definido como indicado aqui e aqui

Druska
fonte
10
Obrigado! O mesmo vale para 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")
Евгений Смирнов
fonte
61
Desativar totalmente o mecanismo de segurança não é uma boa maneira de corrigir o erro.
Guillaume Algis
2
Se você estiver usando cookiecutter-django em 2017, esta é a resposta correta na produção.
André Duarte
1
Por que isso, por curiosidade?
Patrick Gallagher
3
Esta resposta não sugere "desabilitar totalmente o mecanismo de segurança", ela apenas informa como fazer isso em um único caso em que você não poderá usar o token CSRF. Este é o meu caso, onde preciso oferecer uma ação POST para um cliente externo.
mariotomo
Este é um tipo de item TODO que eu uso durante a fase de desenvolvimento, quando você não pode fornecer o token csrf da IU. Mas certamente não é recomendado para um aplicativo ao vivo.
Aman Madan,
24

Se você estiver usando a API HTML5 Fetch para fazer solicitações POST como um usuário conectado e obtendo Forbidden (CSRF cookie not set.), pode ser porque, por padrãofetch não inclui cookies de sessão, fazendo com que o Django pense que você é um usuário diferente daquele que carregou a página .

Você pode incluir o token de sessão passando a opção credentials: 'include'de buscar:

var csrftoken = getCookie('csrftoken');
var headers = new Headers();
headers.append('X-CSRFToken', csrftoken);
fetch('/api/upload', {
    method: 'POST',
    body: payload,
    headers: headers,
    credentials: 'include'
})
user85461
fonte
posso saber qual é o método Header () que você instanciou? é esse método global de javascript?
Abz Rockers
@AbzRockers: Sim, Headersé uma interface global de javascript, parte da API HTML5 Fetch. developer.mozilla.org/en-US/docs/Web/API/Headers
user85461
13

De Este Você pode resolvê-lo adicionando o decorador ensure_csrf_cookie a sua visão

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

se este método não funcionar. você tentará comentar o csrf no middleware. e teste novamente.

dscanon
fonte
5

Eu me deparei com uma situação semelhante ao trabalhar com o DRF, a solução foi anexar o método .as_view () ao modo de exibição em urls.py

Pratik Mhatre
fonte
Seria melhor se você incluísse algum código também
Alex Jolig
1
@AlexJolig acabou de enfrentar o mesmo problema, o problema é que esqueci de adicionar .as_view()aftrer meu ApiView para que a aparência do código: urlpatterns += path('resource', ResourceView)E é assim que deveria ser: urlpatterns += path('resource', ResourceView.as_view())
Alveona
4

Se você estiver usando DRF, verifique se seus padrões de URL estão corretos, talvez você tenha esquecido .as_view() :

Assim era como o meu código parecia:

urlpatterns += path('resource', ResourceView) 

E é assim que deve ser:

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

tente verificar se você instalou no settings.py

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

No modelo, os dados são formatados com o csrf_token:

<form>{% csrf_token %}
</form>
drabo2005
fonte
não tenho todo o seu código, mas acredito que a questão está aqui: def deposit (request, account_num): altere para def deposit (request): e encontre uma maneira de retornar o account_num. agora vai depender se account_num é um campo de tabela ou uma variável.
drabo2005
É uma variável {{account_num}}, mas como isso afeta o token csrf?
Acredito que o token csrf se referiu apenas à solicitação, portanto, ele não pode verificar ou manipular o que está acontecendo com a variável aqui. verifique o djangoproject.com pode ser que você possa obter uma resposta adequada sobre o csrf_token.
drabo2005
1

Isso também ocorre quando você não define a ação do formulário.
Para mim, estava mostrando este erro quando o código era:

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

Quando eu corrigi meu código neste:

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

meu erro desapareceu.

Gokul Yesudoss
fonte
0

O problema parece que você não está lidando com as GETsolicitações de forma adequada ou postando os dados diretamente sem primeiro obter o formulário.

Ao acessar a página pela primeira vez, o cliente enviará a GETsolicitação, nesse caso deverá enviar html com formulário apropriado.

Mais tarde, o usuário preenche o formulário e envia POST solicitação com os dados do formulário.

Sua visão deve 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
fonte
0

Verifique se os cookies do Chrome estão configurados com a opção padrão para sites. Permitir que dados locais sejam definidos (recomendado).

IWS
fonte
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 o método render_to_response pode causar alguns problemas de cookies de resposta.

shenqi0920
fonte
0

Acabei de me encontrar uma vez, a solução é esvaziar os biscoitos. E pode ser alterado durante a depuração de SECRET_KEY relacionado.

JunLe Meng
fonte
0

Limpar o cache do meu navegador corrigiu esse problema para mim. Eu estava alternando entre ambientes de desenvolvimento local para fazer o tutorial django-blog-zinnia depois de trabalhar em outro projeto quando isso aconteceu. A princípio, pensei que mudar a ordem do INSTALLED_APPS para coincidir com o tutorial tinha causado isso, mas eu os coloquei de volta e não consegui corrigi-lo até limpar o cache.

infosmith
fonte
0

Eu estava usando Django 1.10 antes. Portanto, estava enfrentando esse problema. Agora fiz o downgrade para Django 1.9 e está funcionando bem.

indecente
fonte
Usando 1.10.3 eu tive esse problema. Atualizar para 1.10.6 corrigiu isso para mim.
Mike Darmetko
0

Eu tive o mesmo erro, no meu caso adicionar method_decorator ajuda:

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

method_decorator(csrf_protect)
def post(self, request):
    ...
Moszoro
fonte
0

Certifique-se de que o back-end da sessão django está configurado corretamente em settings.py. Então tente isso,

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

Adicione este middleware em settings.pysob MIDDLEWARE_CLASSESouMIDDLEWARE dependendo da versão do django

get_token - Retorna o token CSRF necessário para um formulário POST. O token é um valor alfanumérico. Um novo token é criado, se ainda não houver um definido.

arp
fonte
-4

Na sua opinião, você está usando o decorador csrf ??

from django.views.decorators.csrf import csrf_protect

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

abhishekgarg
fonte