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存储用于令牌。
答案 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
来完成此操作。对于其他库,它将是类似的。
如果您在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
下指定特定主机的需要,在这种情况下,*
和域列表都不起作用。
非常基本的跨站点请求伪造是指另一个域在您的用户已登录并具有会话cookie的情况下向您的后端发出请求。因此它基于cookie并来自第三方域,因此无法访问浏览器中的任何内容。
XSS,跨站点脚本是指有人设法在您的页面上运行脚本,因此也就是您的域名。此类攻击可以访问浏览器中针对该域的任何内容。这包括sessionStorage和localStorage以及浏览器可以读取的普通cookie。
CSRF令牌既存在于会话cookie中,也作为标题与每个API请求一起发送,在保持后端无状态的同时保护CORS和XSS。
所有后端服务都必须:
exp
部分以避免重播JWT。完整的JWT在用作cookie之前使用服务器私钥进行签名,因此无法在未经检测的情况下进行操作。
因此,任何CSRF攻击都会失败,因为它只能间接访问会话cookie,并且无法从中读取CSRF令牌,因此任何请求都将失败。
任何XSS攻击都会失败,因为即使他们可以在localStorage中读取CSRF令牌,他们也无法获取会话cookie。唯一的方法是从浏览器会话中对后端运行请求,虽然这可能是一般情况下这些攻击的工作方式。他们通常会尝试导出会话信息,以便他们可以从另一台服务器发出请求,但这不会在这里工作。