Chia sẻ phiên (cookie) giữa các miền phụ trong Rails?


92

Tôi có một thiết lập ứng dụng trong đó mỗi người dùng thuộc về một công ty và công ty đó có miền phụ (tôi đang sử dụng miền phụ kiểu basecamp). Vấn đề mà tôi đang gặp phải là rails đang tạo nhiều cookie (một cho lvh.me và một cho subdomain.lvh.me) đang gây ra khá nhiều lỗi trong ứng dụng của tôi (chẳng hạn như các tin nhắn flash liên tục mặc dù tất cả các yêu cầu một lần đăng nhập).

Tôi có cái này trong tệp /cofig/initilizers/session_store.rb của mình:

AppName::Application.config.session_store :cookie_store, key: '_application_devise_session', domain: :all

Miền:: tất cả dường như là câu trả lời chuẩn mà tôi tìm thấy trên Google, nhưng điều đó dường như không hiệu quả với tôi. Bất kỳ trợ giúp được đánh giá cao!

Câu trả lời:


74

Khi nó chuyển sang 'miền: tất cả' tạo một cookie cho tất cả các miền phụ khác nhau được truy cập trong phiên đó (và nó đảm bảo rằng chúng được chuyển giữa các yêu cầu). Nếu không có đối số miền nào được chuyển, điều đó có nghĩa là cookie mới được tạo cho mọi miền khác nhau được truy cập trong cùng một phiên và cookie cũ sẽ bị loại bỏ. Những gì tôi cần là một cookie duy nhất liên tục trong suốt phiên, ngay cả khi miền thay đổi. Do đó, việc vượt qua đã domain: "lvh.me"giải quyết được vấn đề trong quá trình phát triển. Điều này tạo ra một cookie duy nhất ở đó giữa các miền phụ khác nhau.

Đối với bất kỳ ai cần giải thích thêm, đây là một liên kết tuyệt vời: http://excid3.com/blog/sharing-a-devise-user-session-across-subdomains-with-rails-3/


2
Cảm ơn Dude .. Tôi đã đối mặt với vấn đề này trong một trong những dự án của mình .. Cuối cùng đã tìm ra giải pháp ..
Shirjeel Alam

3
Đảm bảo sử dụng giống nhau config.secret_key_basetrên tất cả các ứng dụng của bạn, nếu không nó sẽ không thể giải mã cookie.
Bruno Buccolo

5
Tôi không thấy bất kỳ câu hỏi nào liên quan đến vấn đề này cho Rails 4. Bạn có biết điều này đã thay đổi hay không. Tôi không thể làm cho nó hoạt động với dự án của mình. Nó tiếp tục tạo lại các cookie. Cảm ơn.
Andy

Nếu tôi muốn sử dụng CacheStoređể lưu trữ các phiên trong memcached thì sao?
Amit Patel

2
Với Rails4, tôi thấy rằng điều này chỉ làm việc cho các tên miền phụ với dấu gạch ngang nhưng không phải với dấu gạch:Appname::Application.config.session_store :cookie_store, key: '_appname_session', domain: :all, tld_length: 2
user1515295

68

http://excid3.com/blog/sharing-a-devise-user-session-across-subdomains-with-rails-3/

"Phần bạn muốn lưu ý ở đây là nếu bạn đặt: domain =>: all like được đề xuất ở một số nơi, nó chỉ đơn giản là sẽ không hoạt động trừ khi bạn đang sử dụng localhost.: Tất cả đều được mặc định là độ dài TLD là 1 , có nghĩa là nếu bạn đang thử nghiệm với Pow (myapp.dev), nó cũng sẽ không hoạt động vì đó là TLD có độ dài 2. "

Nói cách khác, bạn cần:

 App.config.session_store ... , :domain => :all, :tld_length => 2

Cũng nên xóa cookie của bạn


1
Đây là câu trả lời tốt nhất vì một thay đổi hoạt động trong mọi môi trường (app.com và app.dev). Phần mềm trung gian tùy chỉnh là không cần thiết. Cũng là điểm tốt để xóa cookie!
Turadg

1
bạn đang thiếu, :tld_length => 2
montrealmike

1
Đảm bảo sử dụng giống nhau config.secret_key_basetrên tất cả các ứng dụng của bạn, nếu không nó sẽ không thể giải mã cookie.
Bruno Buccolo

4
:domain => :allsẽ không hoạt động trong Rails 4, hãy thử domain => 'lvh.me', tld_length = 2. Nó workd cho tôi
Minh Triết

1
Với Rails 4.2, tôi đã có được kết quả tốt domain: :all, tld_length: 2khi sử dụng lvh.memiền.
zwippie

24

Tôi đang tìm cách giải quyết vấn đề này mà không cần phải nêu rõ tên miền, vì vậy tôi có thể chuyển đổi giữa localhost, lvh.me và bất kỳ miền nào tôi sẽ sử dụng trong sản xuất mà không phải tiếp tục chỉnh sửa tệp session_store.rb. Tuy nhiên, thiết lập "domain:: all" dường như không hiệu quả với tôi.

Cuối cùng, tôi thấy rằng tôi cần phải nêu rõ tld_length (độ dài miền cấp cao nhất) trong biểu thức đó. Ví dụ: tld_length mặc định là 1 trong khi example.lvh.me có tld_length là 2 và 127.0.0.1.xip.io có tld_length là 5. Vì vậy, những gì tôi có trong tệp session_store.rb cho các miền phụ trên lvh.me đang phát triển và bất kỳ thứ gì khác trong quá trình sản xuất là bên dưới.

MyApp::Application.config.session_store :cookie_store, key: '_MyApp_session', domain: :all, tld_length: 2

Hy vọng điều này sẽ giúp ai đó, vì tôi đã mất một thời gian dài để tìm ra câu trả lời này!


19

Đối với một số lý do thay thế :allbằng miền không hoạt động (rails 3.2.11) đối với tôi. Phải mất một phần Trung gian tùy chỉnh để sửa chữa nó. Dưới đây là tóm tắt về giải pháp đó.

tl; dr: Bạn cần viết Phần mềm Trung gian Rack tùy chỉnh. Bạn cần thêm nó vào của bạn conifg/environments/[production|development].rb. Đây là trên Rails 3.2.11

Các phiên cookie thường chỉ được lưu trữ cho miền cấp cao nhất của bạn.

Nếu bạn nhìn vào Chrome -> Settings -> Show advanced settings… -> Privacy/Content settings… -> All cookies and site data… -> Search {yourdomain.com}Bạn có thể thấy rằng sẽ có các mục nhập riêng biệt cho sub1.yourdomain.comothersub.yourdomain.comyourdomain.com

Thách thức là sử dụng cùng một tệp lưu trữ phiên trên tất cả các miền phụ.

Bước 1: Thêm lớp phần mềm trung gian tùy chỉnh

Đây là nơi Rack Middleware xuất hiện. Một số tài nguyên về rack & rails có liên quan:

Đây là một lớp tùy chỉnh mà bạn nên thêm vào. lib Điều này được viết bởi @Nader và tất cả các bạn nên cảm ơn anh ấy

# Custom Domain Cookie
#
# Set the cookie domain to the custom domain if it's present
class CustomDomainCookie
  def initialize(app, default_domain)
    @app = app
    @default_domain = default_domain
  end

  def call(env)
    host = env["HTTP_HOST"].split(':').first
    env["rack.session.options"][:domain] = custom_domain?(host) ? ".#{host}" : "#{@default_domain}"
    @app.call(env)
  end

  def custom_domain?(host)
    host !~ /#{@default_domain.sub(/^\./, '')}/i
  end
end

Về cơ bản điều này làm được là nó sẽ ánh xạ tất cả dữ liệu phiên cookie của bạn trở lại vào cùng một tệp cookie chính xác bằng với miền gốc của bạn.

Bước 2: Thêm vào cấu hình Rails

Bây giờ bạn có một lớp tùy chỉnh trong lib, hãy đảm bảo rằng bạn đang tự động tải nó. Nếu điều đó không có ý nghĩa gì với bạn, hãy xem tại đây: Tự động tải về Rails 3

Điều đầu tiên là đảm bảo rằng bạn đang sử dụng kho cookie trên toàn hệ thống. Trong config/application.rbchúng tôi yêu cầu Rails sử dụng kho cookie.

# We use a cookie_store for session data
config.session_store :cookie_store,
                     :key => '_yourappsession',
                     :domain => :all

Lý do điều này ở đây được đề cập ở đây là vì :domain => :alldòng. Có những người khác đã đề nghị chỉ định :domain => ".yourdomain.com"thay vì :domain => :all. Vì một số lý do, điều này không hoạt động với tôi và tôi cần lớp Middleware tùy chỉnh như được mô tả ở trên.

Sau đó, trong config/environments/production.rbphần bổ sung của bạn :

config.middleware.use "CustomDomainCookie", ".yourdomain.com"

Lưu ý rằng dấu chấm trước đó là cần thiết. Xem " cookie tên miền phụ, được gửi trong yêu cầu tên miền mẹ? " Để biết lý do.

Sau đó, trong config/environments/development.rbphần bổ sung của bạn :

config.middleware.use "CustomDomainCookie", ".lvh.me"

Thủ thuật lvh.me ánh xạ vào localhost. Thật tuyệt vời. Xem Railscast này về tên miền phụghi chú này để biết thêm thông tin.

Hy vọng rằng điều đó nên làm điều đó. Thành thật mà nói, tôi không hoàn toàn chắc chắn tại sao quá trình này lại phức tạp, vì tôi cảm thấy các trang web tên miền phụ chéo là phổ biến. Nếu bất kỳ ai có thêm hiểu biết về lý do đằng sau mỗi bước này, vui lòng cho chúng tôi biết trong phần bình luận.


Có cách nào để làm cho điều này hoạt động với nhiều miền cấp cao nhất không? Tôi có một sản phẩm chạy ở các quốc gia khác nhau. Ở đây chúng tôi giả định miền mặc định là yourdomain.com, nhưng nếu nó được cho là hoạt động cho .be .sv .fr .com.br .com.ar và những miền khác thì sao? Cảm ơn.
Marc Lainez

Tôi chỉ không thể làm cho nó hoạt động. Tôi đang phát triển trong rails 4 và có vẻ như rials chỉ nhẹ nhàng bỏ qua tất cả mã ở trên. Nó chỉ không muốn chia sẻ phiên trên các miền phụ.
Ole Henrik Skogstrøm

@ OleHenrikSkogstrøm Hãy đảm bảo sử dụng cùng một config.secret_key_baseứng dụng trên tất cả các ứng dụng của bạn, nếu không nó sẽ không thể giải mã cookie.
Bruno Buccolo

17

Tôi bắt gặp điều này khi đang tìm cách đơn giản nhất để đặt cookie thành miền gốc. Có vẻ như có một số thông tin sai lệch về :alltùy chọn khi được chuyển thành tùy chọn miền. Đối với hầu hết các miền, nó sẽ thực sự hoạt động như mong đợi, đặt cookie thành miền gốc (ví dụ: .example.comfor test.example.com). Tôi nghĩ rằng hầu hết mọi người đều gặp sự cố vì họ đang sử dụng miền lvh.međể kiểm tra. Regex được sử dụng bởi rails để tìm một miền cấp cao nhất được định nghĩa là DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/. Nếu bạn lưu ý phần cuối cùng, bạn có thể thấy rằng đường ray diễn giải lvh.menhư một TLD tương tự như com.au. Nếu trường hợp sử dụng của bạn cần lvh.mehoạt động, thì :alltùy chọn này sẽ không hoạt động bình thường, tuy nhiên, nó có vẻ là tùy chọn đơn giản nhất và tốt nhất cho hầu hết các miền.

TL; DR, câu trả lời chính xác ở đây, giả sử bạn không phát triển trên miền 3 ký tự (hoặc bất kỳ miền nào gây nhầm lẫn với regex ở trên) là sử dụng :all.


Cảm ơn bạn, điều này cuối cùng đã giúp tôi hiểu tại sao có rất nhiều câu trả lời đề xuất tld_length là 2 nhưng tại sao tôi lại không cần!
soupdog

Câu trả lời này cần phải cao hơn. Cảm ơn ngài.
luca.busin

"lvh.me dưới dạng TLD tương tự như com.au" BTW Rails thực sự phải diễn giải .me theo cách giống như nó cũng là một miền quốc gia (Montenegro).
mahemoff 13/09/19

7

Rails 4.x (cũng sẽ ổn với các phiên bản Rails 5/6)

Cách lấy lvh.me:3000 và tên miền phụ trong máy chủ cục bộ (Rails)

Phát triển: Tôi đã chia sẻ cookie để thêm .lvh.mevào session_store.rb,

Nó sẽ được chia sẻ giữa các miền con trên localhost admin.lvh.me:3000, lvh.me:3000v.v.

#config/initializers/session_store.rb

domain = Rails.env.production? ? ".domain_name.com" : ".lvh.me"

Rails.application.config.session_store :cookie_store, 
                      key: '_app_name_session', domain: domain

4

Bạn đã thử chưa

AppName::Application.config.session_store :cookie_store, key: '_application_devise_session', domain: 'lvh.me'  

)

về cơ bản, chúng tôi đang nói có một cookie duy nhất cho miền cơ sở và chỉ bỏ qua miền phụ.. mặc dù cách tiếp cận này vẫn còn một số sai sót ...


1

hỗ trợ đường ray5

nếu bạn muốn nó hoạt động với bất kỳ miền nào:

Rails.application.config.session_store :cookie_store, key: '_my_app_session', domain: :all, tld_length: 2

Để định cấu hình cho mỗi môi trường, bạn có thể sử dụng như sau:

Rails.application.config.session_store :cookie_store, key: '_my_app_session', domain: {
  production: '.example.com',
  development: '.example.dev'
}.fetch(Rails.env.to_sym, :all)

Tham khảo: https://github.com/plataformatec/devise/wiki/How-To:-Use-subdomains


0

Nếu bạn đang sử dụng Redis cho cửa hàng phiên.

if Rails.env.development?
    Rails.application.config.session_store :redis_store, {
       servers: [
        { host: 'localhost', port: 6379},
      ],
      key: '_app_session',
      expire_after: 1.day,
      domain: :all
    }

else
    Rails.application.config.session_store :redis_store, {
       servers: [
        { host: HOST_URL, port: PORT},
      ],
      key: '_app_session',
      expire_after: 1.day,
      domain: '.domain.com',
      tld_length: 2
    }
    
end 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.