sử dụng localStorage trên các miền phụ


95

Tôi đang thay thế cookie bằng localStorage trên các trình duyệt có thể hỗ trợ nó (bất kỳ ai trừ IE). Vấn đề là site.comwww . site.com lưu trữ các đối tượng localStorage riêng biệt của họ. Tôi tin rằng www được coi là một miền phụ (một quyết định ngu ngốc nếu bạn hỏi tôi). Nếu người dùng ban đầu trên site.com và quyết định nhập www . site.com trong lần truy cập tiếp theo của cô ấy, tất cả dữ liệu cá nhân của cô ấy sẽ không thể truy cập được. Làm cách nào để tất cả "miền phụ" của tôi dùng chung localStorage như miền chính?


4
Firefox và IE8 hỗ trợ lưu trữ dữ liệu liên tục theo miền do người dùng chỉ định. Ví dụ trên FF, bạn có thể thực hiện globalStorage ['site.com'] và điều này sẽ không hiển thị đối với www.site.com và site.com. Tôi vẫn chưa tìm ra cách thực hiện việc này trong quá trình triển khai của Chrome.
JoJo

9
Cân nhắc sử dụng một hoặc sau này - chuyển hướng tất cả người dùng truy cập bằng www. tên miền phụ với tên miền phụ không có tên miền phụ hoặc ngược lại.
Elad Nava

Tôi đã tạo bài viết từ lâu: Cross-Domain LocalStorage
jcubic

Câu trả lời:


94

Đây là cách tôi sử dụng nó trên các miền ...

  • Sử dụng iframe từ miền mẹ của bạn - giả sử parent.com
  • Sau đó, trên mỗi miền child.com, chỉ cần thực hiện một postMessage tới iframe parent.com của bạn
  • Tất cả những gì bạn cần làm là thiết lập một giao thức về cách diễn giải các thông điệp postMessage của bạn để nói chuyện với iframe parent.com.

Tôi hy vọng nó sẽ giúp :)


2
Đây là câu trả lời thực sự, không phải câu trả lời đã chọn. Tôi đã tự mình thực hiện việc này nhưng cũng đã tạo một trình bao bọc gọi lại tiện lợi với postMessage.
Jason Sebring

4
Đây là một bài viết hay với một số mã ví dụ giải thích phương pháp này: jcubic.wordpress.com/2014/06/20/cross-domain-localstorage
Todd Price

4
Lưu ý rằng điều này chỉ có thể thực hiện được khi cookie của bên thứ ba không bị vô hiệu hóa: stackoverflow.com/a/44097269/4311428
Tối đa

6
Apple đã cập nhật mặc định trên Safari 7+ cả trên máy tính để bàn và thiết bị di động để chặn dữ liệu của bên thứ ba. Tùy chọn hiện được gọi là "Chặn cookie và dữ liệu trang web khác", đề cập đến những thứ như lưu trữ cục bộ hiện được cách ly hoàn toàn theo miền. Đây công việc phương pháp sẽ không trong Safari
Aranganathan

2
@Max @Aranganathan nó vẫn làm việc đối với trường hợp câu hỏi ban đầu - site.com/ www.site.commiễn là tên miền phụ là trên domain cha cùng
Kostiantyn

40

Nếu bạn đang sử dụng giải pháp iframe và postMessage chỉ cho vấn đề cụ thể này, tôi nghĩ có thể sẽ ít công việc hơn (cả về mã và tính toán khôn ngoan) nếu chỉ lưu trữ dữ liệu trong cookie không có tên miền phụ và nếu chưa có trong localStorage khi tải, lấy nó từ cookie .

Ưu điểm:

  • Không cần thiết lập thêm iframe và postMessage.

Nhược điểm:

  • Sẽ cung cấp dữ liệu trên tất cả các miền phụ (không chỉ www), vì vậy nếu bạn không tin tưởng vào tất cả các miền phụ, nó có thể không hoạt động với bạn.
  • Sẽ gửi dữ liệu đến máy chủ theo từng yêu cầu. Không tuyệt vời, nhưng tùy thuộc vào tình huống của bạn, có thể vẫn ít hoạt động hơn giải pháp iframe / postMessage.
  • Nếu bạn đang làm điều này, tại sao không chỉ sử dụng cookie trực tiếp? Phụ thuộc vào bối cảnh của bạn.
  • Kích thước cookie tối đa 4K, tổng số trên tất cả cookie cho miền (Cảm ơn Blake đã chỉ ra điều này trong nhận xét)

Mặc dù vậy, tôi đồng ý với những người bình luận khác, điều này có vẻ như nó phải là một tùy chọn có thể xác định được cho localStorage nên không cần phải có các giải pháp thay thế.


29
Con: Kích thước cookie tối đa 4k
Blake Miller

17
Ngoài ra, như tôi đã học được một cách khó khăn, giới hạn 4k dành cho tổng kích thước của tất cả các cookie cho một tên miền, không phải cho mỗi cookie.
Blake Miller

nhược điểm khác: - cookie có nhiều khả năng sẽ bị chặn bởi adblockers - cookie được sử dụng để chia sẻ dữ liệu nhỏ giữa máy chủ và máy khách, nếu máy chủ không sử dụng dữ liệu bạn lưu trữ trong cookie, do đó đây là một hành vi lạm dụng
Enno

32

Tôi khuyên bạn nên chuyển hướng site.com đến www.site.com để vừa nhất quán vừa tránh các vấn đề như thế này.

Ngoài ra, hãy xem xét sử dụng giải pháp trình duyệt chéo như PersistJS có thể sử dụng bộ nhớ gốc của từng trình duyệt.


Tôi không có quyền truy cập quản trị vào các máy chủ để thực hiện chuyển hướng như vậy. Thư viện đó có cho phép tôi chia sẻ dữ liệu liên tục giữa www và không phải www không? Sau khi thực hiện một số đọc, có vẻ như gần như tất cả các cơ chế lưu trữ của trình duyệt không cho phép điều đó. Không có vấn đề nếu nó cookie hoặc localStorage, chúng ta sẽ gặp phải vấn đề này ...
JoJo

Có, bộ nhớ thường phụ thuộc vào miền, bao gồm cả miền phụ. Đây là lý do tại sao tôi đề xuất một chuyển hướng. Bạn không nhất thiết cần truy cập admin, chỉ cần sử dụng một quy tắc .htaccess trong thư mục gốc tài liệu
Eran Galperin

1
@JoJo Có một số cách để chuyển hướng, ví dụ: bằng cách gửi tiêu đề Locationhoặc thông qua <meta>thẻ HTML, hoặc thậm chí JS qua window.location.
Sony Santos

1
Đây chỉ là tránh câu trả lời. Hãy xem câu trả lời của Mayank là đúng.
Jason Sebring

1
+1 @avoiding, ngoài ra điều này không liên quan đối với các trường hợp khác - như trường hợp mà tôi đang ở đây lang1.domain.com - lang2.domain.com
r --------- k

6

Đặt thành cookie trong miền chính -

document.cookie = "key=value;domain=.mydomain.com"

và sau đó lấy dữ liệu từ bất kỳ miền chính hoặc miền phụ nào và đặt nó trên localStorage



1

loại giải pháp này gây ra nhiều vấn đề như thế này. để có tính nhất quán và cân nhắc SEO chuyển hướng trên tên miền chính là giải pháp tốt nhất.

làm nó chuyển hướng ở cấp máy chủ

Cách chuyển hướng www thành không có www với Nginx

https://www.digitalocean.com/community/tutorials/how-to-redirect-www-to-non-www-with-nginx-on-centos-7

hoặc bất kỳ cấp nào khác như lộ trình 53 nếu đang sử dụng


1

Đây là cách:

Để chia sẻ giữa các miền phụ của một miền siêu cụ thể (ví dụ: example.com), bạn có thể sử dụng một kỹ thuật trong trường hợp đó. Nó có thể được áp dụng cho localStorage, IndexedDB, SharedWorker, BroadcastChannel, vv, tất cả đều cung cấp chức năng chia sẻ giữa các trang cùng một nguồn gốc, nhưng vì một lý do không tôn trọng bất kỳ sửa đổi để document.domaincó thể cho phép họ sử dụng superdomain như nguồn gốc của họ trực tiếp.

(1) Chọn một miền "chính" để chứa dữ liệu: tức là https://example.com hoặc https://www.example.com sẽ giữ dữ liệu localStorage của bạn. Giả sử bạn chọn https://example.com .

(2) Sử dụng localStorage bình thường cho các trang của miền đã chọn đó.

(3) Trên tất cả các trang https://www.example.com ( tên miền khác ), hãy sử dụng javascript để đặt document.domain = "example.com";. Sau đó, cũng tạo một ẩn <iframe>và điều hướng nó đến một số trang trên chọn https://example.com miền ( Nó không quan trọng những gì trang , miễn là bạn có thể chèn một rất ít đoạn mã javascript trên đó. Nếu bạn' đang tạo lại trang web, chỉ cần tạo một trang trống cụ thể cho mục đích này. Nếu bạn đang viết tiện ích mở rộng hoặc tập người dùng kiểu Greasemonkey và do đó, bạn không có bất kỳ quyền kiểm soát nào đối với các trang trên example.commáy chủ, chỉ cần chọn trang nhẹ nhất mà bạn có thể tìm thấy và chèn tập lệnh của bạn vào đó. Một số loại trang "không tìm thấy" có lẽ sẽ ổn).

(4) Tập lệnh trên trang iframe ẩn chỉ cần (a) đặt document.domain = "example.com";và (b) thông báo cho cửa sổ mẹ khi việc này được thực hiện. Sau đó, cửa sổ cha có thể truy cập cửa sổ iframe và tất cả các đối tượng của nó mà không bị hạn chế! Vì vậy, trang iframe tối thiểu giống như:

<!doctype html>
<html>
<head>
  <script>
    document.domain = "example.com";
    window.parent.iframeReady();  // function defined & called on parent window
  </script>
</head>
<body></body>
</html>

Nếu viết usercript, bạn có thể không muốn thêm các chức năng có thể truy cập bên ngoài như iframeReady()vào của bạn unsafeWindow, vì vậy, cách tốt hơn để thông báo cho userscript cửa sổ chính có thể là sử dụng một sự kiện tùy chỉnh:

    window.parent.dispatchEvent(new CustomEvent("iframeReady"));

Bạn có thể phát hiện điều này bằng cách thêm trình xử lý cho sự kiện "iframeReady" tùy chỉnh vào cửa sổ trang chính của bạn.

(LƯU Ý: Bạn cần đặt document.domain = "example.com" ngay cả khi miền của iframe đã là example.com : Việc chỉ định giá trị cho document.domain đặt ngầm định giá trị của cổng thành null và cả hai cổng phải khớp với iframe và nguồn gốc của nó được coi là cùng nguồn gốc. Xem ghi chú tại đây: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changed_origin )

(5) Khi ẩn iframe đã thông báo cửa sổ mẹ của nó mà nó sẵn sàng, kịch bản trong cửa sổ cha mẹ chỉ có thể sử dụng iframe.contentWindow.localStorage, iframe.contentWindow.indexedDB, iframe.contentWindow.BroadcastChannel, iframe.contentWindow.SharedWorkerthay vì window.localStorage, window.indexedDBvv ... và tất cả các đối tượng này sẽ được scoped để lựa chọn https: // nguồn gốc example.com - vì vậy chúng sẽ có cùng nguồn gốc được chia sẻ này cho tất cả các trang của bạn!

Phần khó xử nhất của kỹ thuật này là bạn phải đợi iframe tải trước khi tiếp tục. Vì vậy, bạn không thể chỉ bắt đầu sử dụng localStorage trong trình xử lý DOMContentLoaded một cách dễ dàng. Ngoài ra, bạn có thể muốn thêm một số xử lý lỗi để phát hiện nếu iframe ẩn không tải chính xác.

Rõ ràng, bạn cũng nên đảm bảo iframe ẩn không bị xóa hoặc điều hướng trong suốt thời gian tồn tại của trang ... OTOH Tôi không biết kết quả của việc đó sẽ như thế nào, nhưng rất có thể điều tồi tệ sẽ xảy ra.

Và, một lưu ý: cài đặt / thay đổi document.domaincó thể bị chặn bằng cách sử dụng Feature-Policytiêu đề, trong trường hợp đó, kỹ thuật này sẽ không thể sử dụng được như mô tả.


Tuy nhiên, có một khái quát phức tạp hơn đáng kể về kỹ thuật này, không thể bị chặn Feature-Policyvà điều đó cũng cho phép các miền hoàn toàn không liên quan chia sẻ dữ liệu, thông tin liên lạc và công nhân được chia sẻ (nghĩa là không chỉ miền phụ ngoài một miền siêu cấp chung). @Mayank Jain đã mô tả nó trong câu trả lời của họ, cụ thể là:

Ý tưởng chung là, giống như ở trên, bạn tạo một iframe ẩn để cung cấp nguồn gốc chính xác cho việc truy cập; nhưng thay vì sau đó chỉ lấy các thuộc tính của cửa sổ iframe trực tiếp, bạn sử dụng tập lệnh bên trong iframe để thực hiện tất cả công việc và bạn giao tiếp giữa iframe và cửa sổ chính của mình chỉ bằng cách sử dụng postMessage()addEventListener("message",...).

Điều này hoạt động vì postMessage()có thể được sử dụng ngay cả giữa các cửa sổ có nguồn gốc khác nhau. Nhưng nó cũng phức tạp hơn đáng kể vì bạn phải chuyển mọi thứ qua một số loại cơ sở hạ tầng nhắn tin mà bạn tạo giữa iframe và cửa sổ chính, thay vì chỉ sử dụng API localStorage, IndexedDB, v.v. trực tiếp trong mã của cửa sổ chính của bạn.


0

Đây là cách tôi đã giải quyết nó cho trang web của mình. Tôi đã chuyển hướng tất cả các trang không có www thành www.site.com. Bằng cách này, nó sẽ luôn sử dụng localstorage của www.site.com

Thêm phần sau vào .htacess của bạn , (tạo một cái nếu bạn chưa có) trong thư mục gốc

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

5
Tôi rất muốn phản đối điều này nhưng tôi sẽ không vì nó có thể giúp ích cho trường hợp sử dụng của OP, nhưng đối với những người muốn giữ các phiên trên myapp.com và Develop.myapp.com và support.myapp.com, câu trả lời này là không tốt.
Don Omondi

hey @DonOmondi Tôi sẽ đánh giá cao nếu bạn có thể giúp tôi với các liên kết cho những gì bạn đang đề xuất!
Ayush Baheti

3
OP đã hỏi "sử dụng localStorage trên các miền phụ" câu trả lời của bạn là "chuyển hướng www sang không phải www" những điều rất khác nhau nhưng nó có thể hoạt động nếu và chỉ khi miền phụ cụ thể là "www.abc.com" cho các trường hợp chung, một số câu trả lời khác ở đây là thiết thực hơn.
Don Omondi
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.