Rails 安全会话和 cookie 不适用于 CDN



我的设置如下所示:CloudFront CDN,仅使用 https 和 EC2 Instnace 或仅 http(向 CloudFront 发出的所有请求都是 https,从 CloudFront 向 EC2 发出的所有请求都是 http(

如果我在应用程序中将 secure 设置为true,则会话和 cookie 将不再保存在任何浏览器中。如果我将其设置为false,它可以在大多数浏览器中工作,但在Safari 中不起作用

Rails.application.config.session_store :cookie_store, key: '_K_session', secure: true

我的目标是让会话适用于所有浏览器。我真的不需要安全会话设置。

这是我简化的Terraform设置:

resource "aws_cloudfront_distribution" "main_rails_app" {
origin {
domain_name = "${aws_elastic_beanstalk_environment.main_rails_app.cname}"
origin_id   = "${var.cf_main_rails_app_origin_id}"
custom_origin_config {
http_port              = "80"
https_port             = "443"
origin_protocol_policy = "http-only"
origin_ssl_protocols   = ["TLSv1.1"]
}
}
default_cache_behavior {
allowed_methods  = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods   = ["GET", "HEAD", "OPTIONS"]
target_origin_id = "${var.cf_main_rails_app_origin_id}"
forwarded_values {
query_string = true
headers      = ["*"]
cookies {
forward = "all"
}
}
min_ttl                = 0
default_ttl            = 0
max_ttl                = 0
compress               = true
viewer_protocol_policy = "redirect-to-https"
}
viewer_certificate {
# cloudfront_default_certificate = true
acm_certificate_arn      = "${data.aws_acm_certificate.some_domain.arn}"
minimum_protocol_version = "TLSv1.1_2016"
ssl_support_method       = "sni-only"
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
}

cookie 存储正在做它应该做的事情,Rails 在未加密的会话上收到了一个 cookie,CF 到 EC2 是未加密的。

您有几种选择。

  1. 如果要设置为 secure,请加密 ec2 和 cf 之间的流量:true。以及强制 ssl 重定向。
  2. 保持安全:false,因为您已经信任 CF 和 EC2 之间的连接。

http://guides.rubyonrails.org/v5.0/security.html

未设置安全会话 Cookie

事实证明,Safari 确实会发送位置标头,即使表单托管在同一域上,而其他一些浏览器没有。位置标头值(cdn 网址(将与应用程序网址(ec2 网址(不匹配,请求将在 rails 中标记为无效。我有protect_from_forgery而不是protect_from_forgery with: :exception,我花了很长时间才看到这个,因为我没有收到任何明显的错误。我的解决方案是禁用此设置:

Rails.application.config.action_controller.forgery_protection_origin_check = false

此设置的默认状态在 Rails 5 中被翻转。

最新更新