security - válido - html form without csrf protection solutions
Grails: ¿hay una forma recomendada de lidiar con los ataques CSRF en formularios AJAX? (1)
¡Bonito!
OMI, será mejor que reinicies el token al mismo tiempo.
SynchronizerTokensHolder.store(session).resetToken(params.SYNCHRONIZER_URI)
y si tiene múltiples formularios en la misma página, defina una variable para contener los tokens devueltos de cada solicitud de Ajax.
Por cierto, ¿por qué no implementar el patrón de token por su cuenta?
- Genere un token, por ejemplo,
UUID.randomUUID().toString()
, y guárdelo en sesión con la url como clave. - Verifique y restablezca el token en el estado de las acciones posteriores.
Estoy usando el Patrón de Token Synchronizer para formularios estándar (useToken = true) pero no puedo encontrar ningún método recomendado para tratar esto con AJAX.
EDITAR
Desde que publiqué esto, lancé mi propia solución incorporando el patrón existente de Grails desde arriba.
En jQuery ajax, publico todo el formulario (que incluirá los campos ocultos SYNCHRONIZER_TOKEN y SYNCHRONIZER_URI inyectados de Grails) de modo que el cierre con formato puede funcionar como se espera en el controlador.
El problema es que, en una respuesta exitosa, no hay un nuevo conjunto de tokens (ya que la página no se vuelve a cargar y g: form taglib no se evoca) y lo hago manualmente en el controlador que llama a la misma biblioteca que el formulario g: taglib, y devolverlo en la respuesta ajax, y luego restablecer el valor del campo oculto. Vea abajo:
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);
}
})
en el controlador:
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
}
¿Alguien puede identificar si, sin saberlo, introduje un defecto de seguridad en la solución anterior? Me parece adecuado, pero no me gusta que nada tenga que ver con la seguridad.