Rails - 如何向用 javascript 创建的表单添加 CSRF 保护?
Posted
技术标签:
【中文标题】Rails - 如何向用 javascript 创建的表单添加 CSRF 保护?【英文标题】:Rails - How to add CSRF Protection to forms created in javascript? 【发布时间】:2012-01-20 03:59:48 【问题描述】:我正在使用backbone.js,效果很好。但是我作为 javascript 模板创建的表单缺少 rails csrf 保护令牌。如何将它添加到我在 javascript 中创建的模板中?
【问题讨论】:
【参考方案1】:我解决这个问题的最佳方法,在表单内:
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
更新:
看起来form_authenticity_token
对于较新的 Rails 版本中的控制器是私有的。
如果你是这种情况,我的建议是:在控制器中声明一个变量,例如:
@form_token = form_authenticity_token
并在您正在寻找的视图中使用它。
【讨论】:
它有效,但为什么呢?form_authenticity_token
不是控制器中的私有吗?
这不适用于我 Rails 4.2.2。我得到:undefined local variable or method 'form_authenticity_token' for #<#<Class:0x007ff80b1d36d8>:0x007ff7eec39b58>
嘿伙计们,看起来form_authenticity_token
对于富兰克林所说的控制器来说是私有的。我看到的建议是在控制器@form_token = form_authenticity_token
中声明一个变量并在视图中使用它。
这适用于我在 rails 4.2.5 中。注意:此表单是在 ERB 中生成的,而不是在 JS 中生成的。【参考方案2】:
如果您的布局中有 <%= csrf_meta_tag %>
并且您可以从 js 访问它,那么您可以使用 $('meta[name="csrf-token"]')
访问它
请参阅http://eunikorn.blogspot.com/2011/07/working-with-backbonejs-in-harmony-with.html,了解如何将 csrf 支持加入到每个主干请求中
【讨论】:
请参阅gist.github.com/3482636 了解另一个如何入侵此功能的示例。我不知道是否相同。 具体:$.ajax(data: authenticity_token: $('meta[name="csrf-token"]').attr("content"))
【参考方案3】:
您可以将 csrf 标记添加到每个使用“发布”或“删除”的表单。这是在咖啡脚本中:
$ ->
for f in $("form")
if f.method == 'post' or f.method == 'delete'
$(f).prepend("<input type='hidden' name='authenticity_token' value='" + token + "'>")
确保您的布局中有 。它应该已经在标准的“应用程序”布局中,但如果您使用不同的布局,请添加它。
【讨论】:
token
声明在哪里?
@suga_shane 写“确保你有<%= csrf_meta_tags %>
”的意思是这个Rails 助手为你生成一个令牌并将它插入HTML head
。令牌是<meta>
标记中的content
属性,名称为csrf-token
。【参考方案4】:
我在 Rails 6 应用程序的 Vue 组件中有一个表单。
令我惊讶的是,在 Vue 模板中包含一个名为 authenticity_token
的隐藏输入就足够了,并且在页面加载时,Rails 使用 CSRF 保护令牌填充了该值。
例如
<template>
<div id="app">
<form
action="/submit"
method="post"
@submit.prevent="onSubmit"
>
<input
type="hidden"
name="authenticity_token"
value=""
>
<!-- rest of form -->
</form>
</div>
</template>
渲染为:
<div id="app">
<form action="/submit" method="post">
<input type="hidden" name="authenticity_token" value="zl9PJiE...">
...
</form>
</div>
【讨论】:
【参考方案5】:Rails 4.2.2 不允许使用
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
来自您的 .js.erb
资产文件。
但是,您可以在 .js.erb
文件中创建表单,并在包含表单 .html.erb
文件的视图中使用 hidden_field_tag
帮助器生成令牌元素。由于此元素将在表单之外生成,您可以使用 jquery 将此元素附加到表单中。
案例研究:SweetAlert(第一个版本,似乎也解决了这个问题)
show.js.erb
$('.js-button-apply-offer').click(function(e)
var urlOffer = $(this).attr('data-url-offer');
var modalParams =
type: 'warning',
title: 'add file',
text: '<p>Need to add a file before continuing</p>' // This is a hack for Sweet alert, solved in SweetAlert2 Consider upgrade
+"<form action='"+urlOffer+"' id='formCustomCV' method='post' enctype='multipart/form-data' data-remote='true'>"
+ "<input type='file' name='custom_cv' id='fileToUploadAlert' accept='application/pdf'>\n"
+"</form>",
html: true,
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: 'Send',
cancelButtonText: 'Cancel',
closeOnConfirm: false
swal(modalParams,
function()
var form_token = $('#form_token');
$('#formCustomCV').append(form_token).submit(); //update to submit using ajax
);
show.html.erb
<%= button_tag t('offers.offer.apply'),
class: 'center-block btn btn-success js-button-apply-offer',
id: "js-button-apply-offer",
data:
url_offer: apply_talents_offer_path(@offer),
%>
<%= hidden_field_tag :authenticity_token, form_authenticity_token, id: :form_token %>
【讨论】:
以上是关于Rails - 如何向用 javascript 创建的表单添加 CSRF 保护?的主要内容,如果未能解决你的问题,请参考以下文章
如何访问 Rails escape_javascript 行中的 JavaScript 变量?
在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是不是存在
如何在 Rails 视图中将 Ruby 变量传递给 JavaScript 函数?
如何在 ruby on rails 中访问 rails 助手和嵌入资产 javascript 文件中的 ruby?