2012-05-08 15 views
12

Necesito almacenar algunos datos del lado del cliente y estos datos son demasiado grandes para almacenarlos en una cookie. LocalStorage parecía ser la forma perfecta de hacerlo, pero el sitio web que utilizaré tiene algunas partes que funcionan en https y otras con solo http y, como almacenamiento local, no puede acceder a los datos de https que configuró con http esto ya no parece una solución viable.¿Existe alguna solución alternativa para utilizar html5 localstorage en http y https?

¿Alguna idea de si hay alguna solución para esto? ¿Alguna otra alternativa?

+0

Relacionados (1) [misma localStorage para http y https?] (Http://stackoverflow.com/questions/5144471/same-localstorage-for- http-y-https), (2) [¿Se pueden compartir bases de datos HTML5 y localStorage en los subdominios?] (http://stackoverflow.com/questions/4177803/can-html5-databases-and-localstorage-be-shared-across -subdominios). –

Respuesta

21

Almacenar todos los datos en un dominio, p. https://my.domain.org/.

  • En https protocolos, basta con utilizar localStorage.setItem('key', 'value') para guardar los datos.
  • En http protocolos, incrustar un marco https, y el uso postMessage para guardar los datos:

demostración: http://jsfiddle.net/gK7ce/4/ (con la página de ayuda que se encuentra en http://jsfiddle.net/gK7ce/3/).

// Script at https://my.domain.org/postMessage 
window.addEventListener('message', function(event) { 
    // Domain restriction (to not leak variables to any page..) 
    if (event.origin == 'http://my.domain.org' || 
     event.origin == 'https://my.domain.org') { 
     var data = JSON.parse(event.data); 
     if ('setItem' in data) { 
      localStorage.setItem(data.setItem, data.value); 
     } else if ('getItem' in data) { 
      var gotItem = localStorage.getItem(data.getItem); 
      // See below 
      event.source.postMessage(
       '#localStorage#' + data.identifier + 
       (gotItem === null ? 'null#' : '#' + gotItem), 
       event.origin 
      ); 
     } else if ('removeItem' in data) { 
      localStorage.removeItem(data.removeItem); 
     } 
    } 
}, false); 

En la página http (s), el marco puede estar integrada de la siguiente manera (reemplazar https://my.mydomain.com con la URL real. Tenga en cuenta que sólo puede obtener una referencia al marco, y utilizar el atributo src) :

<iframe name="myPostMessage" src="https://my.domain.org/postMessage" style="display:none;"></iframe> 
// Example: Set the data 
function LSsetItem(key, value) { 
    var obj = { 
     setItem: key, 
     value: value 
    }; 
    frames['myPostMessage'].postMessage(JSON.stringify(obj), 'https://my.domain.com'); 
} 
LSsetItem('key', 'value'); 

Tenga en cuenta que el método es asíncrona, a causa de postMessage. Una implementación del método getItem tiene que ser implementado de manera diferente:

var callbacks = {}; 
window.addEventListener('message', function(event) { 
    if (event.source === frames['myPostMessage']) { 
     var data = /^#localStorage#(\d+)(null)?#([\S\s]*)/.exec(event.data); 
     if (data) { 
      if (callbacks[data[1]]) { 
       // null and "null" are distinguished by our pattern 
       callbacks[data[1]](data[2] === 'null' ? null : data[3]); 
      } 
      delete callbacks[data[1]]; 
     } 
    } 
}, false); 
function LSgetItem(key, callback) { 
    var identifier = new Date().getTime(); 
    var obj = { 
     identifier: identifier, 
     getItem: key 
    }; 
    callbacks[identifier] = callback; 
    frames['myPostMessage'].postMessage(JSON.stringify(obj), 'https://my.domain.com'); 
} 
// Usage: 
LSgetItem('key', function(value) { 
    console.log('Value: ' + value); 
}); 

Tenga en cuenta que cada una devolución de llamada se almacena en un hash. Cada mensaje también contiene un identificador, por lo que la ventana que recibe el mensaje llama a la devolución de llamada correspondiente correcta.

Para completar, aquí está el método LSremoveItem:

function LSremoveItem(key) { 
    var obj = { 
     removeItem: key 
    }; 
    frames['myPostMessage'].postMessage(JSON.stringify(obj), 'https://my.domain.com'); 
} 
+0

Intenté esto, pero cuando el iframe https intenta enviar de nuevo el mensaje a la ventana padre de HTTP aparece un error "JavaScript inseguro intenta acceder al marco con URL ... Los dominios, protocolos y puertos deben coincidir". ¿Alguna idea? – daniels

+1

Cualquier [SSCCE] (http://sscce.org/)? –

+0

Estoy usando esto: https://github.com/mozilla/jschannel y este ejemplo https://github.com/mozilla/jschannel/tree/master/example – daniels

Cuestiones relacionadas