【问题标题】:Using cross-site cookies to post to Rails API from Chrome extension使用跨站点 cookie 从 Chrome 扩展发布到 Rails API
【发布时间】:2020-12-26 04:49:17
【问题描述】:

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

不过,Chrome 在 2020 年初对其处理跨站点请求的方式进行了更改(请参阅 hereherehere)。具体来说,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

有人知道发生了什么吗?

【问题讨论】:

  • 嘿@Yarin,你能解决这个问题吗?
  • @Simon Yea 想出了一个 hack-在下面为你发布的答案

标签: ruby-on-rails google-chrome cookies google-chrome-extension rack


【解决方案1】:

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

解决方法是使用 Chrome extension 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,确实解决了这个问题。

见:

【讨论】:

    猜你喜欢
    • 2016-04-23
    • 1970-01-01
    • 2023-03-10
    • 2016-09-02
    • 2012-06-20
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2016-06-03
    相关资源
    最近更新 更多