Rails:如何在Rails API模式下实现protect_from_forgery [英] Rails: How to implement protect_from_forgery in Rails API mode

查看:57
本文介绍了Rails:如何在Rails API模式下实现protect_from_forgery的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Rails 5 API应用程序( ApplicationController< ActionController :: API ).需要为此API的一个端点添加一个简单的GUI表单.

I have a Rails 5 API app (ApplicationController < ActionController::API). The need came up to add a simple GUI form for one endpoint of this API.

最初,当我尝试呈现表单时,我得到的是 ActionView :: Template :: Error未定义的方法protect_against_forgery?.我向该端点添加了 include ActionController :: RequestForgeryProtection protect_from_forgery with:exception .哪个按预期解决了这个问题.

Initially, I was getting ActionView::Template::Error undefined method protect_against_forgery? when I tried to render the form. I added include ActionController::RequestForgeryProtection and protect_from_forgery with:exception to that endpoint. Which solved that issue as expected.

但是,当我尝试提交此表单时,我得到: 422 不可处理的实体 ActionController :: InvalidAuthenticityToken .我添加了<%= csrf_meta_tags%> ,并验证了其中存在 meta:csrf-param meta:csrf-token 我的标题,而 authenticity_token 出现在我的表单中.(令牌本身互不相同.)

However, when I try to submit this form I get: 422 Unprocessable Entity ActionController::InvalidAuthenticityToken. I've added <%= csrf_meta_tags %> and verified that meta: csrf-param and meta: csrf-token are present in my headers, and that authenticity_token is present in my form. (The tokens themselves are different from each other.)

我已经尝试过, protect_from_forgery前置:true,with:exception ,没有效果.我可以修复"通过注释掉此问题: protect_from_forgery with:exception .但是我的理解是,这将关闭我表格上的CSRF保护.(我想要CSRF保护.)

I've tried, protect_from_forgery prepend: true, with:exception, no effect. I can "fix" this issue by commenting out: protect_from_forgery with:exception. But my understanding is that that is turning off CSRF protection on my form. (I want CSRF protection.)

我想念什么?

更新:

为清楚起见,此应用程序的99%是纯JSON RESTful API.需要向此应用程序添加一个HTML视图和表单.因此,对于一个控制器,我想启用完整的CSRF保护.该应用程序的其余部分不需要CSRF,并且可以保持不变.

To try to make this clear, 99% of this app is a pure JSON RESTful API. The need came up to add one HTML view and form to this app. So for one Controller I want to enable full CSRF protection. The rest of the app doesn't need CSRF and can remain unchanged.

更新2:

我只是将该应用程序的HTML表单和Header的页面源与我编写的另一个常规的Rails 5应用程序进行了比较.标头中的 authenticity_token 和表单中的 authenticity_token 相同.在我遇到问题的API应用中,它们不同.也许那是什么?

I just compared the page source of this app's HTML form and Header with another conventional Rails 5 app I wrote. The authenticity_token in the Header and the authenticity_token in the form are the same. In the API app I'm having the problem with, they're different. Maybe that's something?

更新3:

好吧,我不认为不匹配是问题所在.但是,在正常工作和不正常工作的应用程序之间的进一步比较中,我注意到Network>中没有任何内容.饼干.我在正常运行的应用程序的Cookie中看到很多类似 _my_app-session 的东西.

Ok, I don't the the mismatch is the issue. However, in further comparisons between the working and non-working apps I noticed that there's nothing in Network > Cookies. I see a bunch of things like _my_app-session in the cookies of the working app.

推荐答案

问题出在这里:Rails 5,在API模式下,逻辑上不包括Cookie中间件.没有它,Cookie中没有存储会话 key ,当我验证通过表单传递的令牌时将不使用该会话.

Here's what the issue was: Rails 5, when in API mode, logically doesn't include the Cookie middleware. Without it, there's no Session key stored in a Cookie to be used when validating the token I passed with my form.

有些令人困惑的是,更改 config/initializers/session_store.rb 中的内容无效.

Somewhat confusingly, changing things in config/initializers/session_store.rb had no effect.

我最终在这里找到了解决该问题的方法:添加cookie会话存储返回到Rails API应用,这使我在这里: https://github.com/rails/rails/pull/28009/files 确切地提到了我需要添加到application.rb以恢复工作的Cookie的行:

I eventually found the answer to that problem here: Adding cookie session store back to Rails API app, which led me here: https://github.com/rails/rails/pull/28009/files which mentioned exactly the lines I needed to add to application.rb to get working Cookies back:

config.session_store :cookie_store, key: "_YOUR_APP_session_#{Rails.env}"
config.middleware.use ActionDispatch::Cookies # Required for all session management
config.middleware.use ActionDispatch::Session::CookieStore, config.session_options

这三行加上:

class FooController < ApplicationController
  include ActionController::RequestForgeryProtection
  protect_from_forgery with: :exception, unless: -> { request.format.json? }
  ...

当然还有通过适当的助手生成的表格:

And of course a form generated through the proper helpers:

form_tag(FOO_CREATE_path, method: :post)
  ...

在我的Rails API应用中间找到一个受CSRF保护的表单.

Got me a CSRF protected form in the middle of my Rails API app.

这篇关于Rails:如何在Rails API模式下实现protect_from_forgery的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆