我正在使用同步器令牌模式用于标准格式(useToken = true)但我找不到任何推荐的方法来处理这个问题而不是AJAX。
修改
自发布此内容以来,我已经推出了自己的解决方案,其中包含了上面的Grails现有模式。
在jQuery ajax中,我发布整个表单(包括Grails'注入SYNCHRONIZER_TOKEN和SYNCHRONIZER_URI隐藏字段),以便withForm闭包可以在控制器中按预期执行。
问题是,成功响应后,没有新的令牌集(因为页面没有被重新加载而且g:form taglib没有被激发)所以我在控制器中手动执行此操作,调用与g:form taglib,并在ajax响应中返回它,然后重置隐藏的字段值。 见下文:
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);
}
})
控制器中的:
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
}
任何人都可以确定我是否在上述解决方案中不知不觉地引入了安全漏洞。它看起来对我来说已经足够了,但我不喜欢手动滚动任何与安全有关的事情。
答案 0 :(得分:1)
尼斯!
IMO,你最好同时重置令牌。
SynchronizerTokensHolder.store(session).resetToken(params.SYNCHRONIZER_URI)
如果在同一页面中有多个表单,请定义一个变量以保存从每个ajax请求返回的标记。
顺便问一下,为什么不自己实现令牌模式?UUID.randomUUID().toString()
,并将其存储到会话中,并将该网址作为密钥。