Rails 4:如何在重定向中设置cookies?

6

我有一个控制器,试图获取表单输入,设置cookie的值,然后重定向到一个页面,该页面将从该cookie中获取数据。

问题在于重定向标头中从未设置cookie。

注意:我已在Chrome和FF中进行了测试。Rails版本为4.0.13。在没有重定向的情况下设置cookie的效果符合预期。

以下是控制器代码:

def create
  request.cookies[:foo] = "bar"

  # also tried:
  #   cookies[:foo]="bar"
  #   cookies.signed[:foo]="bar"
  #   cookies[:foo] = {
  #     value: "bar",
  #     expires: 1.month.from_now,
  #     domain: ".myapplicationhostname.com"
  #   }

  redirect_to root_url
end

重定向的响应头中没有Set-Cookie属性,因此在重定向到的路径中的控制器/操作中不可用cookie值。
我发现一些矛盾的证据表明有些浏览器不接受重定向中的cookie,但似乎这不再是问题了?无论如何,FF或Chrome都没有在响应头中显示Set-Cookie,因此这似乎不是浏览器问题。
以下是来自cURL的响应头,注意缺少Set-Cookie:
HTTP/1.1 302 Moved Temporarily
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-UA-Compatible: chrome=1
Location: http://app.mydomain.com:3000/
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
X-Request-Id: 1fc1c7e5-7489-4720-bb70-28588f3abcb6
X-Runtime: 4.688166
Connection: close
Server: thin 1.6.2 codename Doc Brown

如何让Rails在重定向时设置cookie(或者至少设置header)?


标题头有什么问题吗?request.headers["foo"] = "bar" - RAJ
你是否正在重定向到相同的域名? - user1476061
我正在尝试在服务器端设置cookie,通常是通过使用Set-Cookie http头来完成的。虽然我可以尝试手动设置该标头,但这似乎有些不正规。 - Bryan Marble
最终我想要重定向到另一个子域,所以我知道我必须在cookie上显式地设置域为.mydomain.com,但即使在同一域上重定向时也无法正常工作,如上所示。 - Bryan Marble
我试图将一个Rails应用从Rails 3.2升级到4.0,遇到了这个问题,但在升级指南中找不到任何提及。感谢您的撰写! - Andrew Grimm
1个回答

7
看起来问题的根本原因是CSRF保护机制生效了。控制器已经实例化了一个NullCookieJar,当存在潜在的伪造POST时,该机制会阻止写入cookie。
这是因为我的控制器被设置为响应外部表单,因此无法访问CSRF令牌。
所以,如果您在将外部表单提交到Rails应用程序时遇到此问题,您需要禁用CSRF检查或编写自己的验证方法,如SO问题的答案中所述: "Receive POST from External Form"
总结如下:
禁用检查
skip_before_filter :verify_authenticity_token, only: :my_action

自定义检查
skip_before_filter :verify_authenticity_token, :only => :my_action
before_filter :verify_custom_authenticity_token, :only => :my_action

def verify_custom_authenticity_token
  # checks whether the request comes from a trusted source
end

即使你在同一域上尝试,它也无法访问CSRF吗? - Kris Robison
我之前没有在同一个域上尝试过。这是作为表单小部件构建的,旨在供第三方站点使用,它们将发布到我的应用程序。 - Bryan Marble

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