Bagikan sesi (cookie) antara subdomain di Rails?

93

Saya memiliki pengaturan aplikasi di mana setiap pengguna adalah milik sebuah perusahaan, dan perusahaan tersebut memiliki subdomain (saya menggunakan subdomain gaya basecamp). Masalah yang saya hadapi adalah bahwa rails membuat beberapa cookie (satu untuk lvh.me dan satu lagi untuk subdomain.lvh.me) yang menyebabkan beberapa jeda dalam aplikasi saya (seperti pesan flash menjadi persisten meskipun keluar semua permintaan sekali masuk).

Saya memiliki ini di file /cofig/initilizers/session_store.rb saya:

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

Domain:: semua tampaknya merupakan jawaban standar yang saya temukan di Google, tetapi tampaknya itu tidak berhasil untuk saya. Bantuan apa pun dihargai!

Wahaj Ali
sumber

Jawaban:

76

Ternyata 'domain: all' membuat cookie untuk semua subdomain berbeda yang dikunjungi selama sesi itu (dan memastikan bahwa mereka diteruskan di antara permintaan). Jika tidak ada argumen domain yang diberikan, itu berarti cookie baru dibuat untuk setiap domain berbeda yang dikunjungi dalam sesi yang sama dan yang lama akan dibuang. Yang saya butuhkan adalah satu cookie yang tetap ada sepanjang sesi, bahkan ketika domain berubah. Oleh karena itu, lewat domain: "lvh.me"memecahkan masalah dalam pembangunan. Ini menciptakan satu cookie yang tetap berada di sana di antara subdomain yang berbeda.

Bagi siapa pun yang membutuhkan penjelasan lebih lanjut, ini adalah tautan yang bagus: http://excid3.com/blog/sharing-a-devise-user-session-across-subdomains-with-rails-3/

Wahaj Ali
sumber
2
Terima kasih Bung .. Saya telah menghadapi masalah ini di salah satu proyek saya .. Akhirnya menemukan solusinya ..
Shirjeel Alam
3
Pastikan untuk menggunakan hal yang sama config.secret_key_basedi semua aplikasi Anda, atau cookie tidak akan dapat memecahkan kode.
Bruno Buccolo
6
Saya tidak melihat pertanyaan apa pun terkait dengan ini untuk Rails 4. Apakah Anda tahu jika ini telah berubah. Saya tidak bisa membuatnya bekerja dengan proyek saya. Itu terus membuat ulang cookie. Terima kasih.
Andy
Bagaimana jika saya ingin menggunakan CacheStoreuntuk menyimpan sesi di memcache?
Amit Patel
2
Dengan Rails4, saya menemukan bahwa ini hanya berfungsi untuk subdomain dengan tanda hubung tetapi tidak dengan garis bawah: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/

"Bagian yang ingin Anda perhatikan di sini adalah jika Anda menyetel: domain =>: semua suka direkomendasikan di beberapa tempat, ini tidak akan berfungsi kecuali Anda menggunakan localhost.: Semua default ke panjang TLD 1 , yang berarti jika Anda menguji dengan Pow (myapp.dev), ini juga tidak akan berfungsi karena itu adalah TLD dengan panjang 2. "

Dengan kata lain, Anda membutuhkan:

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

Juga ide yang bagus untuk menghapus cookie Anda

montrealmike
sumber
1
Ini adalah jawaban terbaik karena satu perubahan berfungsi di semua lingkungan (app.com dan app.dev). Middleware kustom tidak diperlukan. Poin bagus juga untuk menghapus cookie!
Turadg
1
Anda melewatkan, :tld_length => 2
montrealmike
1
Pastikan untuk menggunakan hal yang sama config.secret_key_basedi semua aplikasi Anda, atau cookie tidak akan dapat memecahkan kode.
Bruno Buccolo
4
:domain => :alltidak akan berfungsi di Rails 4, coba domain => 'lvh.me', tld_length = 2. Ini bekerja untuk saya
Minh Triet
1
Dengan Rails 4.2 saya mendapatkan hasil yang bagus hanya dengan domain: :all, tld_length: 2menggunakan lvh.medomain.
zwippie
24

Saya sedang mencari cara untuk mengatasi masalah ini tanpa harus menyatakan nama domain secara eksplisit, jadi saya bisa beralih antara localhost, lvh.me, dan domain mana pun yang akan saya gunakan dalam produksi tanpa harus terus mengedit file session_store.rb. Namun, menyetel "domain:: semua" tampaknya tidak berhasil untuk saya.

Akhirnya saya menemukan bahwa saya perlu menyatakan tld_length (panjang domain tingkat atas) dalam ekspresi itu. Default tld_length adalah 1 sedangkan example.lvh.me memiliki tld_length 2 dan 127.0.0.1.xip.io memiliki tld_length 5, misalnya. Jadi apa yang saya miliki di file session_store.rb untuk subdomain di lvh.me dalam pengembangan dan apa pun dalam produksi adalah di bawah ini.

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

Semoga ini bisa membantu seseorang, karena saya butuh waktu lama untuk menemukan jawaban ini!

FangedParakeet
sumber
19

Untuk beberapa alasan mengganti :alldengan domain tidak berhasil (rel 3.2.11) untuk saya. Butuh Middleware kustom untuk memperbaikinya. Ringkasan solusi itu ada di bawah.

tl; dr: Anda perlu membuat Rack Middleware khusus. Anda perlu menambahkannya ke fileconifg/environments/[production|development].rb . Ini ada di Rails 3.2.11

Sesi cookie biasanya disimpan hanya untuk domain level teratas Anda.

Jika Anda melihat di Chrome -> Settings -> Show advanced settings… -> Privacy/Content settings… -> All cookies and site data… -> Search {yourdomain.com}Anda dapat melihat bahwa akan ada entri terpisah untuk sub1.yourdomain.comdan othersub.yourdomain.comdanyourdomain.com

Tantangannya adalah menggunakan file penyimpanan sesi yang sama di semua subdomain.

Langkah 1: Tambahkan Kelas Middleware Khusus

Di sinilah Rack Middleware berperan . Beberapa resource rack & rails yang relevan:

Berikut adalah kelas khusus yang harus Anda tambahkan di lib Ini ditulis oleh @Nader dan Anda semua harus berterima kasih padanya

# 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

Pada dasarnya apa yang dilakukannya adalah memetakan semua data sesi cookie Anda kembali ke file cookie yang sama persis dengan domain root Anda.

Langkah 2: Tambahkan ke Konfigurasi Rails

Sekarang Anda memiliki kelas khusus di lib, pastikan sudah memuatnya secara otomatis. Jika itu tidak berarti apa-apa bagi Anda, lihat di sini: Pemuatan otomatis Rails 3

Hal pertama adalah memastikan bahwa Anda menggunakan penyimpanan cookie di seluruh sistem. Di config/application.rbkami memberi tahu Rails untuk menggunakan penyimpanan cookie.

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

Alasan mengapa hal ini disebutkan di sini adalah karena :domain => :allgaris. Ada orang lain yang menyarankan untuk menentukan :domain => ".yourdomain.com"alih-alih :domain => :all. Untuk beberapa alasan ini tidak berhasil untuk saya dan saya membutuhkan kelas Middleware kustom seperti yang dijelaskan di atas.

Kemudian di config/environments/production.rbtambahkan:

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

Perhatikan bahwa titik sebelumnya diperlukan. Lihat " cookie sub-domain, dikirim dalam permintaan domain induk? " Untuk mengetahui alasannya.

Kemudian di config/environments/development.rbtambahkan:

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

Trik lvh.me dipetakan ke localhost. Itu mengagumkan. Lihat Railscast tentang subdomain dan catatan ini untuk info lebih lanjut.

Mudah-mudahan itu harus dilakukan. Sejujurnya saya tidak sepenuhnya yakin mengapa proses ini berbelit-belit, karena saya merasa situs lintas subdomain adalah hal yang umum. Jika ada yang memiliki wawasan lebih jauh tentang alasan di balik masing-masing langkah ini, beri tahu kami di komentar.

Evan
sumber
Adakah cara untuk membuat ini berfungsi dengan beberapa domain level teratas? Saya memiliki produk yang beroperasi di berbagai negara. Di sini kami mengasumsikan domain default adalah domainanda.com, tetapi bagaimana jika domain tersebut berfungsi untuk .be .sv .fr .com.br .com.ar dan lainnya? Terima kasih.
Marc Lainez
Saya tidak bisa mendapatkan ini untuk bekerja. Saya mengembangkan di rails 4 dan sepertinya rial mengabaikan semua kode di atas. Itu hanya tidak ingin berbagi sesi di seluruh subdomain.
Ole Henrik Skogstrøm
@ OleHenrikSkogstrøm Pastikan untuk menggunakan hal yang sama config.secret_key_basedi semua aplikasi Anda, atau aplikasi tidak akan dapat memecahkan kode cookie.
Bruno Buccolo
17

Saya menemukan ini saat mencari cara termudah untuk mengatur cookie menjadi domain root. Tampaknya ada beberapa informasi yang salah tentang :allopsi ketika disahkan sebagai opsi domain. Untuk sebagian besar domain, ini benar-benar akan berfungsi seperti yang diharapkan, menyetel cookie ke domain root (misalnya .example.comuntuk test.example.com). Saya rasa kebanyakan orang mengalami masalah karena mereka menggunakan domain lvh.meuntuk menguji. Regex yang digunakan oleh rails untuk menemukan domain level teratas didefinisikan sebagai DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/. Jika Anda mencatat bagian terakhir, Anda dapat melihat bahwa rails diartikan lvh.mesebagai TLD yang mirip dengan com.au. Jika kasus penggunaan Anda perlu lvh.meberfungsi, maka :allopsi tersebut tidak akan berfungsi dengan baik, namun, tampaknya opsi tersebut paling sederhana dan terbaik untuk sebagian besar domain.

TL; DR, jawaban yang benar di sini, dengan asumsi Anda tidak mengembangkan domain 3 huruf (atau domain apa pun yang membingungkan regex di atas) akan digunakan :all.

cassanego
sumber
Terima kasih, ini akhirnya membantu saya memahami mengapa begitu banyak jawaban merekomendasikan tld_length 2 tetapi mengapa saya tidak perlu!
anjing sup
Jawaban ini harus lebih tinggi. Terima kasih tuan.
luca.busin
"lvh.me sebagai TLD yang mirip dengan com.au" BTW Rails memang harus menafsirkan .me dengan cara yang sama karena ini juga merupakan domain negara (Montenegro).
mahemoff
8

Rails 4.x (juga harus baik-baik saja dengan versi Rails 5/6)

Cara mendapatkan lvh.me:3000 dan subdomain di localhost (Rails)

Pengembangan: Saya telah membagikan cookie untuk ditambahkan .lvh.meke session_store.rb,

Ini akan dibagikan antara subdomain di localhost admin.lvh.me:3000, lvh.me:3000dan seterusnya ...

#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
7urkm3n
sumber
4

Apakah Anda mencoba

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

)

pada dasarnya kami mengatakan memiliki cookie tunggal untuk domain dasar dan abaikan saja sub domain..meskipun pendekatan ini memiliki beberapa kekurangan masih ...

Naveed
sumber
2

rel pendukung5

jika Anda ingin ini berfungsi dengan domain apa pun:

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

Untuk mengkonfigurasi per lingkungan, Anda dapat menggunakan yang berikut ini:

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

Ref: https://github.com/plataformatec/devise/wiki/How-To:-Use-subdomains

cgg5207
sumber
0

Jika Anda menggunakan Redis untuk penyimpanan sesi.

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 
Marcelo Austria
sumber