Używam wzorca tokenu synchronizatora dla standardowych formularzy (useToken = true), ale nie mogę znaleźć żadnej zalecanej metody radzenia sobie z tym przez AJAX.Grails - Czy istnieje zalecany sposób radzenia sobie z atakami CSRF w formularzach AJAX?
EDIT
Od opublikowania tego, mam walcowane moje własne rozwiązanie zawierające Grails dotychczasowego wzoru z góry.
W jQuery ajax umieszczam cały formularz (który zawiera wstrzyknięte pola ukryte SYNCHRONIZER_TOKEN i SYNCHRONIZER_URI) tak, że zamknięcie withForm może działać zgodnie z oczekiwaniami w kontrolerze.
Problem polega na tym, że po pomyślnej odpowiedzi nie ma nowego zestawu znaczników (ponieważ strona nie jest ponownie ładowana, a tag g: form nie jest wywoływany), więc robię to ręcznie w kontrolerze, wywołując tę samą bibliotekę, co g: form taglib, i zwróć go w odpowiedzi ajax, a następnie zresetuj wartość ukrytego pola. Patrz poniżej:
var formData = jQuery("form[name=userform]").serializeArray();
$.ajax({
type: 'POST',
url: 'delete',
data: formData,
success: function (data) {
// do stuff
},
complete: function (data) {
// Reset the token on complete
$("#SYNCHRONIZER_TOKEN").val(data.newToken);
}
})
w kontrolerze:
def delete(String selectedCommonName) {
def messages = [:]
withForm {
User user = User.findByName(name)
if (user) {
userService.delete(user)
messages.info = message(code: 'user.deleted.text')
} else {
messages.error = message(code: 'user.notdeleted.text')
}
}.invalidToken {
messages.error = message(code: 'no.duplicate.submissions')
}
// Set a new token for CSRF protection
messages.newToken = SynchronizerTokensHolder.store(session).generateToken(params.SYNCHRONIZER_URI)
render messages as JSON
}
Czy ktoś może określić, czy ja nieświadomie wprowadził lukę bezpieczeństwa w powyższym roztworze. Wydaje mi się to odpowiednie, ale nie podoba mi się ręczne przetasowanie czegokolwiek związanego z bezpieczeństwem.
Właściwie to od czasu wprowadzenia zmian w tej implementacji odesłanie tokenu dla następnego żądania oznaczało, że osoba atakująca mająca podstawową wiedzę na temat implementacji tokenów synchronizatora Grails mogłaby z powodzeniem ją wykorzystać. Tak więc zachowałem powyższą implementację, aby zapobiec powielaniu formularzy i ulepszałem je za pomocą własnego rozwiązania o zasięgu sesji, generując mój własny identyfikator UUID w taki sam sposób jak wspomniałeś powyżej. – dre
Rozumiem. Może powinieneś pomyśleć o zresetowaniu tokena w 'complete' zamiast' success'. W moim projekcie istnieje mnóstwo odwołań ajaxowych na tej samej stronie, więc dołączam i resetuję tokena w ajaxSend i ajaxStop na całym świecie. – Yang
Tak, dobry punkt na zrobienie tego w * pełnym * zamiast * sukcesie *. Dla mojej własnej realizacji, generuję token i dodam do sesji, jak tylko trafisz kontroler. Nie widzę przewagi ciągłej regeneracji, jest mało prawdopodobne, że ktoś ją zgadnie w rozsądnym czasie. Oczywiście, gdy użytkownik opuści stronę i wróci do niej, generowany jest nowy. – dre