简体   繁体   English

Rails Set-Cookie on json API 响应

[英]Rails Set-Cookie on json API response

Simple token based auth for Rails.简单的基于令牌的 Rails 身份验证。
Client server makes a request to the API server.客户端服务器向 API 服务器发出请求。 The API server returns success status, json-encoded body and ideally sets a cookie. API 服务器返回成功状态、json 编码的正文并理想地设置 cookie。

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

How can this response also set a cookie?此响应如何还设置 cookie?
I've tried to append , set_cookie: token to the render statement.我试图将, set_cookie: token附加到渲染语句。 I've also我也
skip_before_filter :verify_authenticity_token, only: :create

The end goal is to store the token in a browser cookie.最终目标是将令牌存储在浏览器 cookie 中。 I do not want to use HTML5 storage for the token.我不想为令牌使用 HTML5 存储。

This is my setup for a cross-domain SPA/API setup:这是我的跨域 SPA/API 设置:

I have this in my controller, using the Knock gem, action:我在我的控制器中有这个,使用 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

That will set a cookie on the client as well as returning all the token data in the response body, including a CSRF token.这将在客户端上设置一个 cookie,并在响应正文中返回所有令牌数据,包括一个 CSRF 令牌。

You also need to make sure that your AJAX requests include the cookie, which they don't by default.您还需要确保您的 AJAX 请求包含 cookie,默认情况下它们不包含。 With Axios, you do this by setting the option withCredentials: true .使用 Axios,您可以通过设置选项withCredentials: true For other libraries, it will be something similar.对于其他库,它会是类似的。

CORS CORS

If you have CORS configured on the API server, and you should, you need some additional config there as well.如果您在 API 服务器上配置了 CORS,并且您应该这样做,那么您还需要一些额外的配置。 I use the Rack::CORS gem for this and my config looks like this (config/initializers/cors.rb):我为此使用了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

Note the config for credentials: true as well as the need to specify a specific host under origins , neither * nor a list of domains will work in this case.请注意credentials: true的配置credentials: true以及需要在origins下指定特定主机,在这种情况下, *和域列表都不起作用。

CSRF and XSS CSRF 和 XSS

Very basically Cross-Site Request Forgery is when another domain makes a request to your backend on the assumption that your user is logged in and has a session cookie.基本上跨站点请求伪造是当另一个域假设您的用户已登录并具有会话 cookie 向您的后端发出请求时。 So it is based on cookies and come from a third party domain and as such can not access anything in your browser.因此它基于 cookie 并来自第三方域,因此无法访问您浏览器中的任何内容。

XSS, Cross-Site Scripting is when someone manages to run a script on YOUR page, and hence your domain. XSS,跨站点脚本是指有人设法在您的页面上运行脚本,从而在您的域上运行脚本。 This sort of attack can access anything in your browser, for that domain.这种攻击可以访问您浏览器中该域的任何内容。 This includes sessionStorage and localStorage as well as normal cookies that the browser can read.这包括 sessionStorage 和 localStorage 以及浏览器可以读取的普通 cookie。

Why this works为什么这有效

The CSRF token is present both in the session cookie and sent along with each API request as a header, giving protection from both CORS and XSS while keeping the backend stateless. CSRF 令牌存在于会话 cookie 中,并作为标头与每个 API 请求一起发送,在保持后端无状态的同时提供对 CORS 和 XSS 的保护。

All any backend service has to do is:任何后端服务所要做的就是:

  1. Verify the JWT signature (to ensure it's not a faked or manipulated session cookie being returned).验证 JWT 签名(以确保返回的不是伪造或操纵的会话 cookie)。
  2. Verify the exp part to avoid JWT replay.验证exp部分以避免 JWT 重放。
  3. Compare the header CSRF token to the one in the JWT.将标头 CSRF 令牌与 JWT 中的令牌进行比较。
  4. Verify the scopes in the JWT (this will be application specific).验证 JWT 中的范围(这将特定于应用程序)。

The full JWT is signed with the servers private key before being used as a cookie and as such cannot be manipulated without detection.完整的 JWT 在用作 cookie 之前使用服务器私钥进行签名,因此无法在没有检测的情况下进行操作。

So any CSRF attack will fail since it only has indirect access to the session cookie and won't be able to read the CSRF token from it, so any request will fail.因此,任何 CSRF 攻击都会失败,因为它只能间接访问会话 cookie,并且无法从中读取 CSRF 令牌,因此任何请求都会失败。

Any XSS attack will fail because even though they can read the CSRF token in localStorage they can not get the session cookie.任何 XSS 攻击都会失败,因为即使他们可以读取 localStorage 中的 CSRF 令牌,也无法获取会话 cookie。 The only way to do that would be to run requests from your browser session against the backend, and while that could be possible that is not generally how these attacks work.做到这一点的唯一方法是从您的浏览器会话对后端运行请求,虽然这可能是可能的,但这些攻击通常不是这样工作的。 They normally try to export the session info so that they can make requests from another server, and that won't work here.他们通常会尝试导出会话信息,以便他们可以从另一台服务器发出请求,但这在这里不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从rails 3中的响应中删除Set-Cookie标头? - How to remove Set-Cookie header from response in rails 3? 如何在响应中设置域[“ set-cookie”] - How to set domain in response[“set-cookie”] Rails 4:如果type是JSON,请在请求/响应中设置cookie? - Rails 4: Set a cookie in a request/response if type is JSON? 为什么rails不断发回Set-Cookie标头? - Why is rails constantly sending back a Set-Cookie header? 是什么使rails从不输出Set-Cookie标头? - What makes rails never outputs `Set-Cookie` header? ActionDispatch::Cookies 没有在响应中设置 Set-Cookie header 但 response.set_cookie 确实 - ActionDispatch::Cookies not setting Set-Cookie header in response but response.set_cookie does Rails / RSpec:reset_session在集成测试期间不更改Set-Cookie HTTP标头值 - Rails/RSpec: reset_session not changing Set-Cookie HTTP header value during integration tests 为什么Rails会为同一会话的每个请求更改Set-Cookie标头 - Why Rails change Set-Cookie header every request for the same session Rails实际上在哪里为_session_id编写Set-Cookie标头? - Where is Rails actually writing the Set-Cookie header for _session_id? 如何在Rails中为特定响应设置cookie - How to set cookie for specific response in Rails
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM