在json API响应上的Rails Set-Cookie

时间:2015-09-02 13:16:02

标签: ruby-on-rails json api cookies jwt

Rails的基于令牌的简单身份验证 客户端服务器向API服务器发出请求。 API服务器返回成功状态,json编码的主体并理想地设置cookie。

# response from API  
render json: {user: "user", token: "token_string"}, status: :created

此响应如何设置cookie?
我试图将, set_cookie: token附加到render语句中。我也是 skip_before_filter :verify_authenticity_token, only: :create

最终目标是将令牌存储在浏览器cookie中。我不想将HTML5存储用于令牌。

1 个答案:

答案 0 :(得分:1)

这是我对跨域SPA / API设置的设置:

我在我的控制器中使用Knock gem,动作:

class AccountTokenController < Knock::AuthTokenController
  def  create
    response.set_cookie(
      :jwt,
      {
        value: auth_token.token,
        expires: 30.minutes.from_now,
        path: '/api',
        secure: Rails.env.production?,
        httponly: Rails.env.production?
      }
    )

    render json: auth_token.payload, status: :created
  end
end

这将在客户端设置cookie,并返回响应正文中的所有令牌数据,包括CSRF令牌。

您还需要确保您的AJAX请求包含cookie,默认情况下他们不会这样做。使用Axios,您可以通过设置选项withCredentials: true来完成此操作。对于其他库,它将是类似的。

CORS

如果您在API服务器上配置了CORS,那么您应该在那里进行一些额外的配置。我为此使用了Rack::CORS gem,我的配置看起来像这样(config / initializers / cors.rb):

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'http://localhost:3001'
    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head],
      credentials: true
  end
end

请注意credentials: true的配置以及在origins下指定特定主机的需要,在这种情况下,*和域列表都不起作用。

CSRF和XSS

非常基本的跨站点请求伪造是指另一个域在您的用户已登录并具有会话cookie的情况下向您的后端发出请求。因此它基于cookie并来自第三方域,因此无法访问浏览器中的任何内容。

XSS,跨站点脚本是指有人设法在您的页面上运行脚本,因此也就是您的域名。此类攻击可以访问浏览器中针对该域的任何内容。这包括sessionStorage和localStorage以及浏览器可以读取的普通cookie。

为什么会这样?

CSRF令牌既存在于会话cookie中,也作为标题与每个API请求一起发送,在保持后端无状态的同时保护CORS和XSS。

所有后端服务都必须:

  1. 验证JWT签名(以确保它不是返回伪造或操纵的会话cookie)。
  2. 验证exp部分以避免重播JWT。
  3. 将标题CSRF标记与JWT中的标记进行比较。
  4. 验证JWT中的范围(这将是特定于应用程序的。)
  5. 完整的JWT在用作cookie之前使用服务器私钥进行签名,因此无法在未经检测的情况下进行操作。

    因此,任何CSRF攻击都会失败,因为它只能间接访问会话cookie,并且无法从中读取CSRF令牌,因此任何请求都将失败。

    任何XSS攻击都会失败,因为即使他们可以在localStorage中读取CSRF令牌,他们也无法获取会话cookie。唯一的方法是从浏览器会话中对后端运行请求,虽然这可能是一般情况下这些攻击的工作方式。他们通常会尝试导出会话信息,以便他们可以从另一台服务器发出请求,但这不会在这里工作。