Formas de eludir la política del mismo origen
La misma política de origen
Quería crear una wiki comunitaria sobre políticas del mismo origen de HTML/JS para, con suerte, ayudar a cualquiera que busque este tema. Este es uno de los temas más buscados en SO y no existe una wiki consolidada para él, así que allá voy :)
La misma política de origen impide que un documento o script cargado desde un origen obtenga o establezca propiedades de un documento de otro origen. Esta política se remonta a Netscape Navigator 2.0.
¿Cuáles son algunas de sus formas favoritas de evitar las políticas del mismo origen?
Mantenga los ejemplos detallados y preferiblemente vincule también sus fuentes.
El document.domain
método
- Tipo de método: iframe .
Tenga en cuenta que este es un método de iframe que establece el valor de document.domain en un sufijo del dominio actual. Si lo hace, el dominio más corto se utiliza para comprobaciones de origen posteriores. Por ejemplo, supongamos que un script en el documento http://store.company.com/dir/other.html
ejecuta la siguiente declaración:
document.domain = "company.com";
Después de que se ejecute esa declaración, la página pasará la verificación de origen con http://company.com/dir/page.html
. Sin embargo, por el mismo razonamiento, company.com no pudo configurarlo document.domain
en othercompany.com
.
Con este método, se le permitirá ejecutar JavaScript desde un iframe procedente de un subdominio en una página procedente del dominio principal. Este método no es adecuado para recursos entre dominios, ya que navegadores como Firefox no le permitirán cambiar document.domain
a un dominio completamente ajeno.
Fuente: https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript
El método de intercambio de recursos entre orígenes
- Tipo de método: AJAX .
El intercambio de recursos entre orígenes (CORS) es un borrador de trabajo del W3C que define cómo el navegador y el servidor deben comunicarse al acceder a fuentes entre orígenes. La idea básica detrás de CORS es utilizar encabezados HTTP personalizados para permitir que tanto el navegador como el servidor sepan lo suficiente entre sí para determinar si la solicitud o respuesta debe tener éxito o fallar.
Para una solicitud simple, una que utiliza o GET
no POST
encabezados personalizados y cuyo cuerpo es text/plain
, la solicitud se envía con un encabezado adicional llamado Origin
. El encabezado Origen contiene el origen (protocolo, nombre de dominio y puerto) de la página solicitante para que el servidor pueda determinar fácilmente si debe enviar una respuesta o no. Un Origin
encabezado de ejemplo podría verse así:
Origin: http://www.stackoverflow.com
Si el servidor decide que se debe permitir la solicitud, envía un Access-Control-Allow-Origin
encabezado que refleja el mismo origen que se envió o *
si es un recurso público. Por ejemplo:
Access-Control-Allow-Origin: http://www.stackoverflow.com
Si falta este encabezado o los orígenes no coinciden, el navegador rechaza la solicitud. Si todo está bien, el navegador procesa la solicitud. Tenga en cuenta que ni las solicitudes ni las respuestas incluyen información de cookies.
El equipo de Mozilla sugiere en su publicación sobre CORS que se debe verificar la existencia de la withCredentials
propiedad para determinar si el navegador admite CORS a través de XHR. Luego puede combinar la existencia del XDomainRequest
objeto para cubrir todos los navegadores:
function createCORSRequest(method, url){
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr){
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined"){
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
}
var request = createCORSRequest("get", "http://www.stackoverflow.com/");
if (request){
request.onload = function() {
// ...
};
request.onreadystatechange = handler;
request.send();
}
Tenga en cuenta que para que el método CORS funcione, debe tener acceso a cualquier tipo de mecánica de encabezado del servidor y no puede simplemente acceder a ningún recurso de terceros.
Fuente: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
El window.postMessage
método
- Tipo de método: iframe .
window.postMessage
, cuando se llama, hace MessageEvent
que se envíe a en la ventana de destino cuando se completa cualquier script pendiente que deba ejecutarse (por ejemplo, controladores de eventos restantes si window.postMessage
se llama desde un controlador de eventos, tiempos de espera pendientes previamente establecidos, etc.). Tiene MessageEvent
el tipo mensaje, una data
propiedad que se establece en el valor de cadena del primer argumento proporcionado a window.postMessage
, una origin
propiedad correspondiente al origen del documento principal en la ventana que llama window.postMessage
en el momento en que window.postMessage
se llamó y una source
propiedad que es la ventana de Lo que window.postMessage
es llamado.
Para utilizar window.postMessage
, se debe adjuntar un detector de eventos:
// Internet Explorer
window.attachEvent('onmessage',receiveMessage);
// Opera/Mozilla/Webkit
window.addEventListener("message", receiveMessage, false);
receiveMessage
Y se debe declarar una función:
function receiveMessage(event)
{
// do something with event.data;
}
El iframe externo también debe enviar eventos correctamente a través de postMessage
:
<script>window.parent.postMessage('foo','*')</script>
Cualquier ventana puede acceder a este método en cualquier otra ventana, en cualquier momento, independientemente de la ubicación del documento en la ventana, para enviarle un mensaje. En consecuencia, cualquier detector de eventos utilizado para recibir mensajes debe primero verificar la identidad del remitente del mensaje, utilizando las propiedades de origen y posiblemente de origen. Esto no se puede subestimar: no verificar las propiedades origin
y posiblemente source
permita ataques de secuencias de comandos entre sitios.
Fuente: https://developer.mozilla.org/en/DOM/window.postMessage
El método de proxy inverso
- Tipo de método: Ajax
La configuración de un proxy inverso simple en el servidor permitirá que el navegador utilice rutas relativas para las solicitudes de Ajax, mientras que el servidor actuará como un proxy para cualquier ubicación remota.
Si usa mod_proxy en Apache, la directiva de configuración fundamental para configurar un proxy inverso es ProxyPass
. Normalmente se utiliza de la siguiente manera:
ProxyPass /ajax/ http://other-domain.com/ajax/
En este caso, el navegador podría solicitar /ajax/web_service.xml
una URL relativa, pero el servidor actuaría como proxy para http://other-domain.com/ajax/web_service.xml
.
Una característica interesante de este método es que el proxy inverso puede distribuir fácilmente solicitudes hacia múltiples servidores, actuando así como un equilibrador de carga .
Yo uso JSONP.
Básicamente, agregas
<script src="http://..../someData.js?callback=some_func"/>
en tu pagina.
Se debe llamar a some_func() para que se le notifique que los datos están disponibles.
AnyOrigin no funcionó bien con algunos sitios https, así que escribí una alternativa de código abierto llamada whatorigin.org que parece funcionar bien con https.
Código en github .
La forma más reciente de superar la política del mismo origen que encontré es http://anyorigin.com/
El sitio está diseñado para que usted simplemente le dé cualquier URL y genere un código javascript/jquery que le permita obtener el html/datos, independientemente de su origen. En otras palabras, convierte cualquier URL o página web en una solicitud JSONP.
Lo he encontrado bastante útil :)
Aquí hay un ejemplo de código javascript de cualquier origen:
$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
$('#output').html(data.contents);
});
Me viene a la mente el JSONP :
JSONP o "JSON con relleno" es un complemento del formato de datos JSON base, un patrón de uso que permite que una página solicite y use JSON de manera más significativa desde un servidor que no sea el servidor principal. JSONP es una alternativa a un método más reciente llamado intercambio de recursos entre orígenes.