2016-11-10 55 views
7

używam JQuery z ASP.NET Rdzenia 1.0.1 i mam połączenie Ajax:Włącz zabezpieczającym token z ASP.NET Core i JQuery

$("#send-message").on("submit", function (event) { 
    event.preventDefault(); 
    var $form = $(this); 
    $.ajax({ 
    url: "api/messages", 
    data: JSON.stringify($form.serializeToJSON()), 
    dataType: "json", 
    headers: { 
     Accept: "application/json", 
     "Content-Type": "application/json" 
    }, 
    type: "post" 
    }) 
    .done(function (data, status, xhr) { }) 
    .fail(function (xhr, status, error) { }); 

działaniu ASP.NET Rdzeń:

[HttpPost("messages")] 
public async Task<IActionResult> Post([FromBody]MessagePostApiModelModel model) { 
    // Send message 
} 

formularz jest w udostępnionym widzenia i jest on następujący:

<form id="send-question" method="post"> 
    <textarea name="content"></textarea> 
    <button class="button" type="submit">Enviar</button> 
</form> 

Kiedy przesłać formularz pojawia się błąd:

Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The required antiforgery header value "RequestVerificationToken" is not present. 

Jak mogę włączyć AntiForgeryToken programu ASP.NET Core za pomocą wywołań JQuery Ajax?

UPDATE

muszę dodać następujący Asp-Asp-kontrolera i działania do postaci:

<form asp-controller="QuestionApi" asp-action="Post" id="send-question" method="post"> 
</form> 

To wygeneruje token zabezpieczającym. I musiałem ręcznie dodać token nagłówkach wywołania JQuery następująco:

headers: { 
    "Accept": "application/json", 
    "Content-Type": "application/json", 
    "RequestVerificationToken": $form.find("input[name='af_token']").val() 
    }, 

Czy istnieje lepszy sposób to zrobić?

Jak rozwiązać ten problem, gdy nie ma formularza i mam tylko znacznik A, który po kliknięciu wywołuje połączenie Ajax? Czy mogę wygenerować wspólny token antiforgery na mojej stronie głowy, który będzie używany przez wszystkie wywołania ajax z tej strony?

+1

Czy formularz wygenerował stronę serwera przy użyciu helpera formularza? Jeśli tak jest, token zostanie automatycznie wygenerowany dla ciebie jako pole [ukryte dane wejściowe] (http://stackoverflow.com/questions/30959972/html-antiforgerytoken-still-required), więc będzie uwzględniony w form.serializeToJSON'. Bez względu na odpowiedź potrzebny jest również atrybut '[ValidateAntiForgeryToken]' w akcji kontrolera. –

+0

@ DanielJ.G. Czy jest on generowany po stronie serwera, ale nie używam asp-controller i asp-action, ponieważ przesyłam go za pomocą JQuery. Właśnie aktualizuję moje pytanie. Czy czegoś brakuje? –

+0

Potrzebowałem dodać ręcznie następujący nagłówek w moim wywołaniu JQuery: headers: {"RequestVerificationToken": $ form.find ("input [nazwa = 'af_token]". Val() }, ... Czy jest lepszy droga? –

Odpowiedz

10

mode777 za potrzebuje tylko niewielki dodatek do tej pracy (próbowałem go) :

$(document).ajaxSend(function(e, xhr, options) { 
    if (options.type.toUpperCase() == "POST") { 
     var token = $form.find("input[name='af_token']").val(); 
     xhr.setRequestHeader("RequestVerificationToken", token); 
    } 
}); 

Właściwie, jeśli również złożyć za pomocą Ajax, nie trzeba korzystać z formularza w ogóle. umieścić to w swoim _layout:

<span class="AntiForge"> @Html.AntiForgeryToken() </span> 

wtedy Pickup token dodając to do javascript:

$(document) 
    .ajaxSend(function (event, jqxhr, settings) { 
     if (settings.type.toUpperCase() != "POST") return; 
     jqxhr.setRequestHeader('RequestVerificationToken', $(".AntiForge" + " input").val()) 
}) 

@HtmlAntiForgeryToken generuje pole wejściowe ukryte z tokenem zabezpieczającym, to samo jak przy korzystaniu z formularza. Powyższy kod znajduje go za pomocą selektora klasy w celu wybrania zakresu, a następnie pobiera w nim pole wejściowe, aby pobrać token i dodać go jako nagłówek.

+0

Sprawdź wygenerowaną nazwę tokena, w asp.core 1.1 to __RequestVerificationToken, więc musisz odpowiednio zmienić nazwę = '... –

+1

Jeśli chodzi o komentarz @Pietera van Kampena, to po prostu zauważ, że nazwa pola formularza nie zaczyna się od podwójnego podkreślenia, ale nazwa nagłówka nie. – jmcilhinney

+0

Jest łatwiejszy sposób na uzyskanie tych danych bez konieczności wprowadzania niczego niepotrzebnego w dokumencie HTML, zobacz moją odpowiedź. – ygoe

0

można zarejestrować zdarzenia globalnego ajax że doda nagłówek do wszystkich połączeń ajax, które nie dostać się w ten sposób: Odpowiedź

$(document).ajaxSend(function(e, xhr, options) { 
    if (options.type.toUpperCase() != "GET") { 
     xhr.setRequestHeader("RequestVerificationToken", token); 
    } 
}); 
3

Uwaga: Ta odpowiedź dotyczy programu ASP.NET Core 2.0. Może nie pasować do starszych wersji.

Oto co zrobiłem po wykopaniu przez kodzie źródłowym aspnet za krótką chwilę:

public static class HttpContextExtensions 
{ 
    public static string GetAntiforgeryToken(this HttpContext httpContext) 
    { 
     var antiforgery = (IAntiforgery)httpContext.RequestServices.GetService(typeof(IAntiforgery)); 
     var tokenSet = antiforgery.GetAndStoreTokens(httpContext); 
     string fieldName = tokenSet.FormFieldName; 
     string requestToken = tokenSet.RequestToken; 
     return requestToken; 
    } 
} 

można go używać w widoku jak ten:

<script> 
    var data = { 
     yourData: "bla", 
     "__RequestVerificationToken": "@Context.GetAntiforgeryToken()" 
    }; 
    $.post("@Url.Action("ActionName")", data); 
</script> 

może zmodyfikować metoda rozszerzenia zwracająca nazwę pola w dowolnej formie, np. sol. fragment JSON.

+1

Wydaje się, że jest to lepsze podejście niż metoda iniekcji i funkcji opisana w dokumentach, ponieważ w widoku zawsze znajduje się obiekt Kontekst, bez dodatkowych "rzeczy" wymaganych. – Erikest