Eu poderia usar alguma ajuda em conformidade com o mecanismo de proteção CSRF do Django através do meu post AJAX. Eu segui as instruções aqui:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
Copiei exatamente o código de exemplo AJAX que eles têm nessa página:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
Coloquei um alerta imprimindo o conteúdo getCookie('csrftoken')
antes da xhr.setRequestHeader
chamada e ele é realmente preenchido com alguns dados. Não sei como verificar se o token está correto, mas sou encorajado por encontrar e enviar algo.
Mas o Django ainda está rejeitando meu post no AJAX.
Aqui está o meu JavaScript:
$.post("/memorize/", data, function (result) {
if (result != "failure") {
get_random_card();
}
else {
alert("Failed to save card data.");
}
});
Aqui está o erro que estou vendo no Django:
[23 / fev / 2011 22:08:29] "POST / memorize / HTTP / 1.1" 403 2332
Tenho certeza de que estou perdendo alguma coisa, e talvez seja simples, mas não sei o que é. Eu pesquisei no SO e vi algumas informações sobre como desativar a verificação do CSRF para a minha visualização pelo csrf_exempt
decorador, mas acho isso desagradável. Eu tentei isso e funciona, mas eu prefiro que meu POST funcione da maneira que o Django foi projetado para esperar, se possível.
Caso isso seja útil, aqui está a essência do que minha visão está fazendo:
def myview(request):
profile = request.user.profile
if request.method == 'POST':
"""
Process the post...
"""
return HttpResponseRedirect('/memorize/')
else: # request.method == 'GET'
ajax = request.GET.has_key('ajax')
"""
Some irrelevent code...
"""
if ajax:
response = HttpResponse()
profile.get_stack_json(response)
return response
else:
"""
Get data to send along with the content of the page.
"""
return render_to_response('memorize/memorize.html',
""" My data """
context_instance=RequestContext(request))
Obrigado por suas respostas!
Respostas:
Solução real
Ok, eu consegui rastrear o problema. Está no código Javascript (como sugeri abaixo).
O que você precisa é este:
em vez do código publicado nos documentos oficiais: https://docs.djangoproject.com/en/2.2/ref/csrf/
O código de trabalho vem desta entrada do Django: http://www.djangoproject.com/weblog/2011/feb/08/security/
Portanto, a solução geral é: "use o manipulador ajaxSetup em vez do manipulador ajaxSend". Não sei por que isso funciona. Mas funciona para mim :)
Post anterior (sem resposta)
Estou enfrentando o mesmo problema, na verdade.
Ocorre após a atualização para o Django 1.2.5 - não houve erros nas solicitações de AJAX POST no Django 1.2.4 (o AJAX não estava protegido de forma alguma, mas funcionou bem).
Assim como o OP, tentei o snippet JavaScript publicado na documentação do Django. Estou usando o jQuery 1.5. Também estou usando o middleware "django.middleware.csrf.CsrfViewMiddleware".
Tentei seguir o código do middleware e sei que ele falha com isso:
e depois
este "se" é verdadeiro, porque "request_csrf_token" está vazio.
Basicamente, isso significa que o cabeçalho NÃO está definido. Então, há algo errado com esta linha JS:
?
Espero que os detalhes fornecidos nos ajudem a resolver o problema :)
fonte
ajaxSetup
em vez deajaxSend
vai contra os docs jQuery: api.jquery.com/jQuery.ajaxSetupSe você usar a
$.ajax
função, poderá simplesmente adicionar ocsrf
token no corpo dos dados:fonte
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
csrfmiddlewaretoken: '{{ csrf_token }}'
ao meudata
dicionário em uma$.post
chamada.Adicione esta linha ao seu código jQuery:
E feito.
fonte
CSRF Failed: CSRF token missing or incorrect.
O problema é que o django espera que o valor do cookie seja devolvido como parte dos dados do formulário. O código da resposta anterior está recebendo o javascript para procurar o valor do cookie e colocá-lo nos dados do formulário. Essa é uma maneira adorável de fazer isso do ponto de vista técnico, mas parece um pouco detalhado.
No passado, eu fiz isso de maneira mais simples, obtendo o javascript para colocar o valor do token nos dados da postagem.
Se você usar {% csrf_token%} em seu modelo, receberá um campo de formulário oculto emitido que carrega o valor. Mas, se você usar o {{csrf_token}}, obterá apenas o valor básico do token, para poder usá-lo em javascript como este ....
Em seguida, você pode incluir isso, com o nome da chave necessário no hash e depois enviar os dados para a chamada ajax.
fonte
window
objeto, para que elas sejam acessíveis posteriormente. Mesmo em arquivos estáticos.O
{% csrf_token %}
colocar em modelos html dentro<form></form>
traduz para algo como:
então por que não apenas cumprimentá-lo em seu JS assim:
e depois passar, por exemplo, fazendo algum POST, como:
fonte
Resposta não-jquery:
uso:
fonte
Se o seu formulário for postado corretamente no Django sem JS, você poderá aprimorá-lo progressivamente com ajax sem nenhuma invasão ou passagem desorganizada do token csrf. Basta serializar o formulário inteiro e isso selecionará automaticamente todos os campos do formulário, incluindo o campo csrf oculto:
Eu testei isso com o Django 1.3+ e o jQuery 1.5+. Obviamente, isso funcionará para qualquer formulário HTML, não apenas para aplicativos Django.
fonte
Use o Firefox com Firebug. Abra a guia 'Console' enquanto dispara a solicitação ajax. Com
DEBUG=True
você obtém a boa página de erro do django como resposta e você pode até ver o html renderizado da resposta do ajax na guia console.Então você saberá qual é o erro.
fonte
A resposta aceita é provavelmente um arenque vermelho. A diferença entre o Django 1.2.4 e 1.2.5 foi o requisito para um token CSRF para solicitações AJAX.
Me deparei com esse problema no Django 1.3 e foi causado pelo cookie CSRF não estar definido em primeiro lugar. O Django não definirá o cookie, a menos que seja necessário. Portanto, um site exclusivo ou fortemente ajax em execução no Django 1.2.4 nunca teria potencialmente enviado um token para o cliente e a atualização que requer o token causaria os erros 403.
A correção ideal está aqui: http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#page-uses-ajax-without-any-html-form,
mas você teria que esperar pelo 1.4, a menos que isso é apenas documentação que acompanha o código
Editar
Observe também que os documentos posteriores do Django observam um bug no jQuery 1.5, portanto, verifique se você está usando a versão 1.5.1 ou posterior com o código sugerido pelo Django: http://docs.djangoproject.com/en/1.3/ref/contrib/csrf/# ajax
fonte
ensure_csrf_cookie
que você pode agrupar uma exibição para garantir que ela envie o cookie.csrftoken
cookie em primeiro lugar, obrigado!Parece que ninguém mencionou como fazer isso em JS puro usando o
X-CSRFToken
cabeçalho e{{ csrf_token }}
, então, aqui está uma solução simples em que você não precisa pesquisar nos cookies ou no DOM:fonte
Como não está indicado em nenhum lugar nas respostas atuais, a solução mais rápida se você não estiver incorporando js ao seu modelo é:
Coloque
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
antes da sua referência ao arquivo script.js no seu modelo e adicionecsrfmiddlewaretoken
ao seudata
dicionário no seu arquivo js:fonte
Acabei de encontrar uma situação um pouco diferente, mas semelhante. Não tenho 100% de certeza se isso seria uma solução para o seu caso, mas resolvi o problema para o Django 1.3 definindo um parâmetro POST 'csrfmiddlewaretoken' com a string de valor de cookie adequada, que geralmente é retornada no formato HTML doméstico pelo Django sistema de modelos com a tag '{% csrf_token%}'. Eu não experimentei o Django mais antigo, apenas aconteceu e resolvi no Django1.3. Meu problema foi que a primeira solicitação enviada via Ajax a partir de um formulário foi concluída com êxito, mas a segunda tentativa exata do mesmo falhou, resultou no estado 403, mesmo que o cabeçalho 'X-CSRFToken' seja corretamente colocado com o valor do token CSRF como no caso da primeira tentativa. Espero que isto ajude.
Saudações,
Hiro
fonte
você pode colar esse js no seu arquivo html, lembre-se de colocá-lo antes de outras funções do js
fonte
Um token CSRF é atribuído a cada sessão (ou seja, toda vez que você efetua login). Portanto, antes de desejar obter alguns dados inseridos pelo usuário e enviá-los como chamada ajax para alguma função protegida pelo decorador csrf_protect, tente encontrar as funções que estão sendo chamadas antes de obter esses dados do usuário. Por exemplo, algum modelo deve estar sendo renderizado no qual o usuário está inserindo dados. Esse modelo está sendo renderizado por alguma função. Nesta função, você pode obter o token csrf da seguinte maneira: csrf = request.COOKIES ['csrftoken'] Agora, passe esse valor de csrf no dicionário de contexto para o qual o modelo em questão está sendo renderizado. Agora, nesse modelo, escreva esta linha: Agora, na sua função javascript, antes de fazer o pedido ajax, escreva o seguinte: var csrf = $ ('# csrf'). val () seleciona o valor do token passado para o modelo e o armazena na variável csrf. Agora, ao fazer uma chamada ajax, em seus dados de postagem, passe esse valor também: "csrfmiddlewaretoken": csrf
Isso funcionará mesmo se você não estiver implementando formulários django.
De fato, a lógica aqui é: Você precisa de um token que pode ser obtido mediante solicitação. Portanto, você só precisa descobrir a função que está sendo chamada imediatamente após o login. Depois de obter esse token, faça outra chamada ajax para obtê-lo ou passe-o para algum modelo acessível pelo seu ajax.
fonte
csrftoken: csrftoken
vez decsrfmiddlwaretoken: csrftoken
. Após a mudança, funcionou. Graçaspara alguém que se depara com isso e está tentando depurar:
1) a verificação do django csrf (assumindo que você está enviando uma) está aqui
2) No meu caso,
settings.CSRF_HEADER_NAME
foi definido como 'HTTP_X_CSRFTOKEN' e minha chamada AJAX estava enviando um cabeçalho chamado 'HTTP_X_CSRF_TOKEN' para que as coisas não funcionassem. Eu poderia alterá-lo na chamada AJAX ou na configuração do django.3) Se você optar por alterá-lo no lado do servidor, encontre o local de instalação do django e instale um ponto de interrupção no
csrf middleware
arquivo .f que estiver usandovirtualenv
, será algo como:~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py
Em seguida, verifique se o
csrf
token foi originado corretamente de request.META4) Se você precisar alterar seu cabeçalho, etc - altere essa variável no seu arquivo de configurações
fonte
Se alguém está lutando com axios para fazer esse trabalho, isso me ajudou:
Fonte: https://cbuelter.wordpress.com/2017/04/10/django-csrf-with-axios/
fonte
No meu caso, o problema foi com a configuração do nginx que copiei do servidor principal para um temporário com a desativação do https que não é necessário no segundo no processo.
Eu tive que comentar essas duas linhas na configuração para fazê-lo funcionar novamente:
fonte
Aqui está uma solução menos detalhada fornecida pelo Django:
Fonte: https://docs.djangoproject.com/en/1.11/ref/csrf/
fonte