[英]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.对于其他库,它会是类似的。
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
下指定特定主机,在这种情况下, *
和域列表都不起作用。
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。
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:任何后端服务所要做的就是:
exp
part to avoid JWT replay.exp
部分以避免 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.