使用跨站点 cookie 从 Chrome 扩展发布到 Rails API

问题描述 投票:0回答:2

我构建了一个 Chrome 扩展程序,可以将 Web 内容保存到我的 Rails 应用程序中。最初我能够依靠现有的 Rails/Devise 用户会话来确保内容被保存到正确的用户,只要在我的 API 控制器上打开 CORS 设置(见下面的代码)。只要用户已登录,无论在哪个网站上使用该扩展程序,从 Chrome 扩展程序对我网站的 AJAX 调用都会得到正确验证。

但是,在 2020 年初,Chrome 对其处理跨站点请求的方式进行了更改(请参阅此处此处此处)。具体来说,cookie 的 SameSite 属性现在默认为“Lax”而不是“None”,因此要使用跨站点 cookie,需要将 cookie 设置明确设置为

SameSite=None; Secure
.

Rails 自己的用户会话 cookie 没有

SameSite=None; Secure
设置,因此使用 Rails 会话来验证我的 Chrome 扩展程序的请求不再是一个选项。

我的修复是在用户登录应用程序时生成我自己的 API 身份验证 cookie,这确实应用了必要的

SameSite=None; Secure
。我能够使用这个 cookie 验证来自我的 Chrome 扩展程序的 API 调用,一切都很好。

然后在 2020 年 9 月上旬,它突然停止工作。 Rails 不再从 Chrome 扩展请求中读取跨站点 cookie。没有错误或警告,值为空。

API控制器:

  # This gets called when user logs into app:
  def set_cross_site_cookie

    # NOTE: Won't work in dev because secure = true
    cookies[:foo_cookie] = {
      value: 'bar',
      expires: 1.year.from_now,
      same_site: :none, # Required in order to access from Chrome extension on different site
      secure: true # Required in order to access from Chrome extension on different site
    }
    cookie = cookies[:foo_cookie]
    render json: {cookie: cookie}

  end

  # This SHOULD work when called from our Chrome extension:
  def get_cross_site_cookie

    # Add headers to allow CORS requests
    # SEE: http://stackoverflow.com/questions/298745/how-do-i-send-a-cross-domain-post-request-via-javascript
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Request-Method'] = %w{GET POST OPTIONS}.join(",")

    cookie = cookies[:foo_cookie]
    render json: {cookie: cookie}

  end

Rails 5,机架 2.1 (注意:为了使用选项

same_site: none
设置 Rails cookie,您显然需要使用高于 2.1.0 的机架版本 - 请参阅:https://github.com/rails/rails/pull/28297 #issuecomment-600566751)

有人知道发生了什么吗?

ruby-on-rails google-chrome cookies google-chrome-extension rack
2个回答
2
投票

我仍然不知道为什么跨站点 cookie 突然停止工作,但我是这样破解它的:

解决方法是使用 Chrome 扩展 cookie API 将我的 Rails API 身份验证 cookie 读取到 Chrome 的本地存储中。由于我们可以在扩展清单中启用对任何特定站点的 cookie 的访问,实际上它们是否是跨站点 cookie 并不重要。

一旦 API cookie 被读入存储,我们就可以将它作为身份验证令牌与每个请求一起传递,基本上将其用作伪 cookie。

所以完整的流程是用户点击扩展按钮,扩展根据它对该域的显式 cookie 权限读取 API 身份验证 cookie,如果 cookie 丢失或过时,它会强制用户登录. 如果 cookie 有效,它会在每个 API 调用的参数或标头中作为身份验证令牌传递。

关于飞行前选项请求的旁注:

您可能还必须处理将通过某些跨站点 AJAX 发送的 OPTIONS 飞行前请求(我认为这只是内容类型 JSON POSTS 的问题,但不要引用我的话),因为它们会触发Rails 中的

ActionController::RoutingError (No route matches [OPTIONS])
错误。推荐的答案是使用rack-cors gem,确实解决了这个问题。

见:


-2
投票

这篇文章提供了一个简单但有效的解决方案,可以使用 Rails 和 React 绕过跨站点 cookie。使用扩展可以在开发环境中工作,但是当您在生产环境中部署您的应用程序时会发生什么?你会要求你的用户也安装扩展吗?

基本上,解决方案是在您的 package.json 文件中添加代理属性,如下所示

"proxy": "http://localhost:3000"
,运行
npm install
,然后重新启动您的应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.