无法验证CSRF令牌真实性Rails/React

10

我在我的Rails应用程序中有一个React组件,我试图使用fetch()向我的本地主机上托管的Rails应用程序发送一个POST请求,这给了我一个错误:

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

我正在使用devise gem来处理user/registrationslogins

我尝试删除protect_from_forgery with: :exception

这是我的获取(fetch)代码:

this.state.ids.sub_id});
  fetch(POST_PATH, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: body  
  }).then(res => res.json()).then(console.log);

我该如何获取CSRF令牌并通过表单发送,以便它会被接受?
理想情况下,我希望只通过标头发送它,但我不知道如何访问该令牌。

4个回答

20

如果你只是将React组件嵌入Rails视图中,最简单的方法是从Rails视图中检索csrf令牌,然后将其作为标头传递给fetch api调用。

您可以通过类似以下的方式获取csrf令牌:

const csrf = document.querySelector("meta[name='csrf-token']").getAttribute("content");

然后你只需在fetch调用中将其作为头部传递:

... headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf }, ...

我通常不使用fetch,所以对确切的语法不太确定,但这应该有助于指导您。


1
但是Rails 5及更高版本现在不是有每个表单的CSRF令牌吗?这个方法还能用吗? - Peter Gerdes

2
感谢您的请求!我得出的工作解决方案如下:

在呈现我的React组件的视图中

。原始答案翻译成“最初的回答”。我会优化语言并使其更加易懂,但需要保留HTML标签。
<% csrf_token = form_authenticity_token %>

<%= react_component('ExerciseDisplay', {
  program: @program.subprograms.first.exercises, ids: {sub_id: @program.subprograms.first.id, team_id: @team.id, token: csrf_token}
}) %>

我将令牌传递给状态,然后通过fetch访问:

  fetch(POST_PATH, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': this.state.ids.token
      },
      body: body  
}).then(res => res.json()).then(console.log);

0

在你的 form 元素中添加一个 authenticity_token

<input type="hidden" name="authenticity_token" value={csrf}/>

按照以下设置值:

const csrf = document.querySelector("meta[name='csrf-token']").getAttribute("content");

-2

1
这似乎是一个安全风险,不是吗? - Samuel Faure
@SamuelFaure 我不是专家,也许你是对的,请参考附加的链接。 - Jose Kj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接