Utilidad para compartir el mismo espacio de localStorage entre varios dominios (o subdominios) distintos.
Si tienes varias webs, o varias formas de acceder a una web como www.miweb.com, miweb.com, wiki.miweb.com, etc.., la información almacenada por cualquiera de ellas con javaScript en el espacio de localStorage del navegador, no será accesible para el resto de dominios. Esto se puede solventar mediante el uso de un iframe oculto y la función postMessage soportada por la mayoría de navegadores.
El truco consiste en cargar un iframe con la URL con la que quieras almacenar la información, y pasarle las peticiones de setItem o getItem a dicho frame. La principal diferencia es que esas funciones son síncronas con localStorage, pero hay que hacerlas asíncronas para adaptarlas al sistema de comunicación entre el iframe y la página contenedora.
En principio necesitamos el archivo html con el código del iframe en el servidor, por ejemplo (código en GitHub), y añadir tus dominios a la lista whitelist:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
<!doctype html> <!-- Based on Nicholas C. Zakas post: --> <!-- credit: http://www.nczonline.net/blog/2010/09/07/learning-from-xauth-cross-domain-localstorage/ --> <html> <body> <script type="text/javascript"> (function(){ //allowed domains (that can use RegExp) var whitelist = ["localhost", "127.0.0.1", "^.*\.domain\.com"]; function verifyOrigin(origin){ var domain = origin.replace(/^https?:\/\/|:\d{1,4}$/g, "").toLowerCase(), i = 0, len = whitelist.length; while(i < len) { if (domain.match(new RegExp(whitelist[i]))) { return true; } i++; } return false; } function handleRequest(event){ if (verifyOrigin(event.origin)) { var request = JSON.parse(event.data); var storage = request.storage; if (request.type == 'get') { value = window[storage].getItem(request.key); event.source.postMessage(JSON.stringify({ id: request.id, key:request.key, value: value }), event.origin); } else if (request.type == 'set') { window[storage].setItem(request.key, request.value); } else if(request.type == 'remove') { window[storage].removeItem(request.key); } } } if(window.addEventListener) { window.addEventListener("message", handleRequest, false); } else if (window.attachEvent) { window.attachEvent("onmessage", handleRequest); } })(); </script> </body> </html> |
Con esto ya podemos usar esta función (crossDomainStorage) para el almacenamiento entre dominios. Ejemplo de uso:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//If you are testing in your local computer, you can leave the default values in // the crossd_iframe.html file, then switch the url between "localhost" and "127.0.0.1", // and see in the localStorage of your browser how it works (see previous Notes). //Once you've added your domain to the `whitelist` in the crossd_iframe.html: var options = { origin: "http://www.example.com", path: "/path/to/iframe.html" }; Storage = crossDomainStorage(options); //... Storage.setItem('key', 'value'); //... Storage.getItem('key', function(key, value) { //if key was not present, value will be 'undefined' if (value !== 'undefined') { //... } else { //key not found... } }); |
Otra cuestión es que, al contrario que las cookies, localStorage no tiene “fecha de caducidad” y para según qué usos el espacio ocupado puede crecer hasta alcanzar el límite del navegador a medio/largo plazo. Para ello he implementado un par de clases que definen una lista con un tamaño prefijado, una de ellas almacena directamente en localStorage y la otra usa la clase anterior “crossDomainStorage” para hacerlo de forma asíncrona a través del iframe.
Puedes encontrar el código completo en GitHub.
localStorage/sessionStorage con un número máximo de elementos (limitedStorage.js)
Para crear el objeto se indican el número máximo de elementos que contendrá. Opcionalmente se puede especificar el almacenamiento que se quiere usar (localStorage o sessionStorage), y un prefijo para los nombres de las variables en dicho sistema de almacenamiento. (el resto de la documentación y más ejemplos en el repositorio en GitHub)
Es una cola: Si se alcanza el límite, primero en entrar -> primero en salir
Si se añade un elemento que ya estaba (con “set(key, item)”), será puesto al final de la cola de nuevo.
Se puede usar igual que los objetos localStorage o sessionStorage:
Funciones:
- setItem(key, value) ‘value’ debe ser serializable con JSON.stringify.
- getItem(key) Si la clave no existe devuelve null
- removeItem(key) Borra el valor asociado a la clave
Ejemplo de uso:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
lstorage = limitedStorage({maxItems: 20, prefix: '_test_'}); //max: 20 items //Note that the specified number of max items (20) are smaller //than the number of keys to store in the following loop (100): for (var i = 0; i<=100; i++) { lstorage.setItem("key-"+i, {'a_tag': 'a value - '+i, 'other_tag': 'other value - '+i}); } //There must be only the last 20 values for (var i = 0; i<=100; i++) { value = lstorage.getItem("key-"+i); if (value !== null) { //you'll need a <div id="results"></div> in your test page... document.getElementById('results').innerHTML += "<br/>found: key-"+i+", value: "+JSON.stringify(value); } } |
Very good article, Just I need.
Thank you!!!
tengo dos dominios locales, (mi-dominio.local y subdominio.mi-dominio.local) desde mi-dominio.local logro cargar el subdomino y su localstorage, el problema es cuando quiero acceder a alguna key de ese subdominio, no me permiete acceder, utilizo este código
Storage = cross_domain_storage({origin: “http://mi-dominio.local”, path: ‘//subdominio.mi-dominio.local/logout’});
cdstorage = cross_domain_list_storage(Storage, {max_items:20 , var_name:’crossD_storage’});
necesito declarar algo mas?
mi idea es acceder a las keys del localstorage del subdominio para eliminarlos y no logro hacerlos , espero puedan auxiliarme
Esto no funciona con Internet Explorer 11 con Windows 7.