Eu implementei no meu aplicativo a atenuação de ataques CSRF, seguindo as informações que li em algum post de blog na Internet. Em particular, este post foi o driver da minha implementação
- Práticas recomendadas para o ASP.NET MVC da equipe de conteúdo do desenvolvedor do ASP.NET e das Ferramentas da Web
- Anatomia de um ataque de falsificação de solicitação entre sites do blog de Phil Haack
- AntiForgeryToken no ASP.NET MVC Framework - Atributo Html.AntiForgeryToken e ValidateAntiForgeryToken do blog de David Hayden
Basicamente, esses artigos e recomendações afirmam que, para impedir o ataque do CSRF, qualquer pessoa deve implementar o seguinte código:
1) Adicione o [ValidateAntiForgeryToken]
em todas as ações que aceitam o verbo POST Http
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SomeAction( SomeModel model ) {
}
2) Adicione o <%= Html.AntiForgeryToken() %>
auxiliar nos formulários que enviam dados ao servidor
<div style="text-align:right; padding: 8px;">
<%= Html.AntiForgeryToken() %>
<input type="submit" id="btnSave" value="Save" />
</div>
De qualquer forma, em algumas partes do meu aplicativo, eu estou fazendo POSTs do Ajax com jQuery para o servidor sem ter nenhum formato. Isso acontece, por exemplo, em que estou permitindo que o usuário clique em uma imagem para executar uma ação específica.
Suponha que eu tenha uma tabela com uma lista de atividades. Eu tenho uma imagem em uma coluna da tabela que diz "Marcar atividade como concluída" e quando o usuário clica nessa atividade, estou executando o Ajax POST, como no exemplo a seguir:
$("a.markAsDone").click(function (event) {
event.preventDefault();
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: {},
success: function (response) {
// ....
}
});
});
Como posso usar o <%= Html.AntiForgeryToken() %>
nesses casos? Devo incluir a chamada auxiliar dentro do parâmetro de dados da chamada Ajax?
Desculpe pelo longo post e muito obrigado por ajudar
EDIT :
De acordo com a resposta do jayrdub , usei da seguinte maneira
$("a.markAsDone").click(function (event) {
event.preventDefault();
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: {
AddAntiForgeryToken({}),
id: parseInt($(this).attr("title"))
},
success: function (response) {
// ....
}
});
});
Respostas:
Eu uso uma função js simples como esta
Como todos os formulários de uma página terão o mesmo valor para o token, basta colocar algo assim na sua página principal
Em seguida, na sua chamada ajax do (editada para corresponder ao seu segundo exemplo)
fonte
AddAntiForgeryToken
, assim:data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
ajaxSend
ou substituirajax
para sempre aumentardata
com o token anti-falsificação? Talvez adicione alguma verificação para garantir que ourl
destino seja destinado ao seu servidor.Gosto da solução fornecida pelo 360Airwalk, mas ela pode ser melhorada um pouco.
O primeiro problema é que, se você criar
$.post()
dados vazios, o jQuery não adiciona umContent-Type
cabeçalho e, nesse caso, o ASP.NET MVC falha ao receber e verificar o token. Então você precisa garantir que o cabeçalho esteja sempre lá.Outra melhoria é o suporte a todos os verbos HTTP com conteúdo : POST, PUT, DELETE etc. símbolo.
fonte
.ajaxSend()
estados "No jQuery 1.8, o método .ajaxSend () deve ser anexado apenas ao documento". api.jquery.com/ajaxsendoptions
vem, que está listado naif
declaração final ? Obrigado.Eu sei que existem muitas outras respostas, mas este artigo é bom e conciso e obriga você a verificar todos os seus HttpPosts, não apenas alguns deles:
http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/
Ele usa cabeçalhos HTTP em vez de tentar modificar a coleção de formulários.
Servidor
Cliente
fonte
Sinto-me como um necromante avançado aqui, mas isso ainda é um problema 4 anos depois no MVC5.
Para lidar com solicitações de ajax corretamente, o token anti-falsificação precisa ser passado para o servidor em chamadas de ajax. A integração nos dados e modelos de postagem é confusa e desnecessária. Adicionar o token como um cabeçalho personalizado é limpo e reutilizável - e você pode configurá-lo para não precisar se lembrar de fazê-lo todas as vezes.
Há uma exceção - o ajax discreto não precisa de tratamento especial para chamadas de ajax. O token é passado normalmente no campo de entrada oculta regular. Exatamente o mesmo que um POST comum.
_Layout.cshtml
No _layout.cshtml, tenho esse bloco JavaScript. Ele não grava o token no DOM, mas usa o jQuery para extraí-lo do literal de entrada oculto que o MVC Helper gera. A seqüência mágica que é o nome do cabeçalho é definida como uma constante na classe de atributo.
Observe o uso de aspas simples na função beforeSend - o elemento de entrada que é renderizado usa aspas duplas que quebrariam o literal JavaScript.
JavaScript do cliente
Quando isso é executado, a função beforeSend acima é chamada e o AntiForgeryToken é adicionado automaticamente aos cabeçalhos da solicitação.
Biblioteca do Servidor
É necessário um atributo personalizado para processar o token não padrão. Isso se baseia na solução da @ viggity, mas lida com ajax discreto corretamente. Esse código pode ser escondido em sua biblioteca comum
Servidor / Controlador
Agora você acabou de aplicar o atributo à sua ação. Melhor ainda, você pode aplicar o atributo ao seu controlador e todos os pedidos serão validados.
fonte
$.ajaxSetup
definir umbeforesend
manipulador de eventos geral , pode ser que você o substitua. Encontrei outra solução onde você pode adicionar um segundo manipulador que também será chamado. Funciona bem e não interrompe sua implementação.Não use Html.AntiForgeryToken . Em vez disso, use AntiForgery.GetTokens e AntiForgery.Validate da API da Web, conforme descrito em Impedindo ataques de falsificação de solicitação entre sites (CSRF) no aplicativo ASP.NET MVC .
fonte
Eu estava apenas implementando esse problema real no meu projeto atual. Eu fiz isso para todos os ajax-POSTs que precisavam de um usuário autenticado.
Primeiro, decidi ligar minhas chamadas jquery ajax, para não me repetir com muita frequência. esse snippet javascript garante que todas as chamadas ajax (post) adicionem meu token de validação de solicitação à solicitação. Nota: o nome __RequestVerificationToken é usado pela estrutura .Net para que eu possa utilizar os recursos padrão do Anti-CSRF, como mostrado abaixo.
Nas vistas em que você precisa que o token esteja disponível para o javascript acima, basta usar o HTML-Helper comum. Basicamente, você pode adicionar esse código onde quiser. Coloquei-o em uma instrução if (Request.IsAuthenticated):
No seu controlador, basta usar o mecanismo padrão do ASP.Net MVC Anti-CSRF. Eu fiz assim (embora eu realmente usei Salt).
Com o Firebug ou uma ferramenta similar, você pode ver facilmente como suas solicitações POST agora têm um parâmetro __RequestVerificationToken anexado.
fonte
Acho que tudo que você precisa fazer é garantir que a entrada "__RequestVerificationToken" esteja incluída na solicitação POST. A outra metade das informações (ou seja, o token no cookie do usuário) já é enviada automaticamente com uma solicitação AJAX POST.
Por exemplo,
fonte
AntiForgeryToken
, é discutível. Se isso acontecer (sem saber como você está conseguindo um nesse caso, mas supondo que esteja), o procedimento acima funcionaria perfeitamente. Se você estiver tentando criar uma página da Web simples que postará uma solicitação em um servidor esperando o referido token e o servidor não gerou a página, você estará sem sorte. Isso é essencialmente o ponto da AntiForgeryToken ...Você também pode fazer isso:
Isso está sendo usado
Razor
, mas se você estiver usandoWebForms
sintaxe, também poderá usar<%= %>
tagsfonte
Além do meu comentário contra a resposta da @ JBall que me ajudou ao longo do caminho, esta é a resposta final que funciona para mim. Estou usando o MVC e o Razor e estou enviando um formulário usando o jQuery AJAX para poder atualizar uma exibição parcial com alguns resultados novos e não desejar fazer uma postagem completa (e oscilação da página).
Adicione o
@Html.AntiForgeryToken()
interior do formulário como de costume.Meu código do botão de envio AJAX (ou seja, um evento onclick) é:
Deixei a ação "success", pois mostra como a exibição parcial está sendo atualizada que contém um MvcJqGrid e como está sendo atualizada (grade jqGrid muito poderosa e esse é um brilhante wrapper MVC para ele).
Meu método de controlador é assim:
Eu tenho que admitir que não sou um fã de postar dados de um formulário inteiro como um modelo, mas se você precisar fazer isso, essa é uma maneira de funcionar. O MVC apenas facilita muito a ligação de dados, em vez de subornar 16 valores individuais (ou um FormCollection de tipo fraco), tudo bem, eu acho. Se você souber melhor, informe-me, pois quero produzir um código MVC C # robusto.
fonte
encontrou essa ideia muito inteligente em https://gist.github.com/scottrippey/3428114 para cada chamada de $ .ajax, modifica a solicitação e adiciona o token.
fonte
if (options.contentType != false && options.contentType.indexOf('application/json') === 0) {
para pegar chamadas Ajax que não tinha especificado um tipo de conteúdo1.Define a função para obter o token do servidor
2. Obtenha o token e defina o cabeçalho antes de enviar para o servidor
3. Validação Onserver no HttpRequestBase no método que você lida com Post / get
fonte
Sei que já faz algum tempo desde que esta pergunta foi publicada, mas achei um recurso realmente útil, que discute o uso do AntiForgeryToken e o torna menos problemático de usar. Ele também fornece o plugin jquery para incluir facilmente o token antiforgery nas chamadas AJAX:
Receitas de solicitações antifalsificação para ASP.NET MVC e AJAX
Não estou contribuindo muito, mas talvez alguém ache útil.
fonte
fonte
Aqui está a maneira mais fácil que eu já vi. Nota: verifique se você tem "@ Html.AntiForgeryToken ()" na sua exibição.
fonte
Pequena melhoria na solução 360Airwalk. Isso imbui o token anti-falsificação dentro da função javascript, portanto, @ Html.AntiForgeryToken () não precisa mais ser incluído em todas as visualizações.
fonte
fonte
Estou usando uma postagem do ajax para executar um método de exclusão (acontece de uma linha do tempo visjs, mas isso não é relelvant). Isto é o que eu sis:
Este é o meu Index.cshtml
Tudo o que eu adicionei aqui foi
@Html.AntiForgeryToken()
fazer o token aparecer na páginaEntão, no meu post do ajax, usei:
O que adiciona o valor do token, raspado da página, aos campos postados
Antes disso, tentei colocar o valor nos cabeçalhos, mas recebi o mesmo erro
Sinta-se livre para publicar melhorias. Esta certamente parece ser uma abordagem simples que eu posso entender
fonte
Ok, muitas postagens aqui, nenhuma delas me ajudou, dias e dias do google, e ainda não cheguei ao ponto de escrever o aplicativo inteiro do zero, e então notei essa pequena pepita no meu Web.confg
Agora não sei por que o adicionei, mas notei que ele é ignorado no modo de depuração e não no modo de produção (IE instalado no IIS em algum lugar)
Para mim, a solução era uma das duas opções, já que não me lembro por que a adicionei. Não posso ter certeza de que outras coisas não dependem dela. Segundo, o nome do domínio deve estar em letras minúsculas e um TLD não como o feito. em * .localLookup.net
Talvez ajude, talvez não. Espero que ajude alguém
fonte
A solução que encontrei não é para o ASPX, mas para o Razor, mas é um problema bastante agradável.
Eu o resolvi adicionando o AntiForgery à solicitação. O HTML Helper não cria um ID HTML com a chamada
Para adicionar o token ao póstrequest, adicionei o ID do AntiForgery ao campo oculto com jquery:
Isso fez com que o controlador aceite a solicitação com o atributo [ValidateAntiForgeryToken]
fonte
O antiforgeryToken ainda é uma dor, nenhum dos exemplos acima funcionou palavra por palavra para mim. Muitos para estão lá. Então eu combinei todos eles. Precisa de um @ Html.AntiforgeryToken em um formulário pendurado no iirc
Resolvido da seguinte forma:
Em caso de dúvida, adicione mais sinais de $
fonte