我的设置如下所示: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 是未加密的。
您有几种选择。
- 如果要设置为 secure,请加密 ec2 和 cf 之间的流量:true。以及强制 ssl 重定向。
- 保持安全: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 中被翻转。