window.document.domain
variable to the same domain name as the parent’s domain name.http://www.qnimate.com/parent.html
<script>
window.document.domain = "www.qnimate.com";//you also need to set the parent's document.domain variable
window.document.getElementById("myIFrame").contentWindow.document.body.style.backgroundColor = "red";//this access is allowed by default
</script>
window.document.domain = "www.qnimate.com"; //if we remove this line then the below line will not work and throw a same origin policy exception.
window.parent.document.body.style.backgroundColor = "blue";
</script>
http://www.qnimate.com/parent.html
echo file_get_contents('http://www.blog.qnimate.com/child.html');
?>
window.document.domain = "www.qnimate.com"; //if we remove this line then the below line will not work and throw a same origin policy exception.
window.parent.document.body.style.backgroundColor = "blue";
</script>
http://www.qnimate.com/parent.html
<script>
var eventMethod = window.addEventListener ? "addEventListener" :"attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" :"message";
// Listen to message from child window
eventer(messageEvent,function(e) {
if(e.data == "changebgofparent")
{
document.body.style.backgroundColor = "blue";
}
},false);
window.document.getElementById("myIFrame").contentWindow.postMessage("changebgofchild","*");
/*postMessage second parameter represents the domain name to which this message can be sent to, if the child domain name doesn't match then this message will not be sent. Here * means any domain */
</script>
var eventMethod = window.addEventListener ? "addEventListener" :"attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" :"message";
// Listen to message from child window
eventer(messageEvent,function(e) {
if(e.data == "changebgofchild")
{
document.body.style.backgroundColor = "red";
}
},false);
window.parent.postMessage("changebgofparent","*");
/*postMessage second parameter represents the domain name to which this message can be sent to, if the child domain name doesn't match then this message will not be sent. Here * means any domain */
</script>
Same Origin Policy for AJAX
- Proxy server
- JSONP
- Cross-Origin Resource Sharing
function loadXMLDoc()
{
var xmlhttp;
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
else
{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","http://www.qnimate.com/ajaxdata.php",true);
xmlhttp.send();
}
</script>
</head>
<body>
<button type="button" onclick="loadXMLDoc()">Request data</button>
<div id="myDiv"></div>
echo file_get_contents('http://www.qscutter.com/ajaxdata.txt');
?>
tag can retrieve a JSON from a cross domain url. We can take advantage of this feature and make a request to cross origin url. This way of bypassing cross origin policy is called JSONP.
The name itself indicates that we load JSON data dynamically using tags and make use of that data using JavaScript. But loading JSON directly using
tags will raise a error because it cannot be accessed until its assigned to a variable. So we can wrap the JSON data around a function call. So the “P” in JSONP indicated padding JSON around a function call.
Let’s see an example of this
http://www.qnimate.com/index.html
<script type="text/javascript">
function dynamicLoad()
{
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'http://www.qscutter.com/ajaxdata.js';
document.getElementById("myBody").appendChild(script);
}
function parseJSON(JSONdata)
{
alert(JSONdata.name);
}
dynamicLoad();
script>
http://www.qscutter.com/ajaxdata.js
The recommended way of bypassing cross origin policy for AJAX is using Cross-Origin Resource Sharing. CORS is a W3C HTTP specification that allows cross-domain communication using AJAX Object. CORS comes in two varieties: simple CORS and complex CORS.
Simple CORS can be used in case you want to make a GET or POST request along with common headers(Accept, Accept-Language, Content-Language, Last-Event-ID and Content-Type with these values only application/x-www-form-urlencoded, multipart/form-data, text/plain). If you want to make any other kind of request then you have to use Complex CROS.
Let’s see an example of Simple CORS
http://www.qnimate.com/index.html
var CROSObject = null;
if(typeof(XMLHttpRequest) != "undefined")
{
//XMLHttpRequest2 is required for CORS Request
CROSObject = new XMLHttpRequest();
//setting this variable to true allows sending and receiving of cokkies.
CROSObject.withCredentials = true;
}
else if(typeof(XDomainRequest) != "undefined")
{
//For IE XDomainRequest is required for CORS request
CROSObject = new XDomainRequest();
//XDomainRequest doesn't support sending and receiving of cookies.
}
else
{
CROSObject = null;
}
if(CROSObject != null)
{
/*
All browsers set Origin Header while sending an AJAX Request
Some don't include this header if the AJAX request is for same domain.
*/
CROSObject.open("GET", "http://www.qscutter.com/ajaxData.php");
CROSObject.onload = function() {alert(CROSObject.responseText);};
CROSObject.onerror = function() {alert("There was an error")};
CROSObject.send();
}
script>
http://www.qscutter.com/ajaxData.php
//Access-Control-Allow-Origin contains the response to be valid for
//requests from specific domain. set it to * for all domains. Its
//a must include header
header("Access-Control-Allow-Origin: http://www.qnimate.com");
//If withCredentials is set to true then this header needs to be
//included otherwise remove this header.
header("Access-Control-Allow-Credentials: true");
//If you want getResponseHeaders() to access other headers rather
//than the basic ones than include this header with the accessiable
//headers names.
header("Access-Control-Expose-Headers: Access-Control-Allow-Credentials, Access-Control-Allow-Origin");
echo "Response text";
?>
Let’s see an example of complex CROS:
http://www.qnimate.com/index.html
var CROSObject = null;
if(typeof(XMLHttpRequest) != "undefined")
{
CROSObject = new XMLHttpRequest();
CROSObject.withCredentials = true;
}
else if(typeof(XDomainRequest) != "undefined")
{
CROSObject = new XDomainRequest();
}
else
{
CROSObject = null;
}
if(CROSObject != null)
{
CROSObject.open("PUT", "http://www.qscutter.com/ajaxData.php");
CROSObject.onload = function() {alert(CROSObject.responseText);};
CROSObject.onerror = function() {alert("There was an error")};
CROSObject.send();
}
script>
http://www.qscutter.com/ajaxData.php
//First check weather the request is preflight or actual. If the request if preflight check if the type of request is PUT.
//If its a PUT request allow further operation otherwise stop it.
//A preflight request will contain the following headers.
//Access-Control-Request-Method is set to the method of the actual request
//Access-Control-Request-Headers is set to a list of headers that doesn't constitute to simple CROS.
//Origin set to the requesting URL
if(isset($_SERVER["Access-Control-Request-Method"]))
{
if($_SERVER["Access-Control-Request-Method"] == "PUT")
{
//you can also check Origin and Access-Control-Request-Headers for valid origin and headers
//This is a positive response so that browser will make actual request
header("Access-Control-Allow-Origin: " .$_SERVER["Origin"]);
header("Access-Control-Allow-Methods: PUT");//list of allowed methods. you can comma seperate other methods also
//header("Access-Control-Allow-Headers: X-Custom-Header");//list of allowed headers
//header("Access-Control-Allow-Credentials: true"); //to allow cookies use
//header("Access-Control-Max-Age: 100000");//caching preflight request and response
}
else
{
//don't allow browser to make actual request
}
}
else
{
//Its a actual request otherwise
if(isset($_SERVER["Origin"]))
{
//validate origin if you want to
header("Access-Control-Allow-Origin: " .$_SERVER["Origin"]);
echo "This is the response";
}
}
?>
Same Origin Policy for data storage
Data stored in the browser (inside localStorage and IndexedDB) are allowed to be accessed only from the same origin which stored it. Two webpages (parent and frame) from different origins can access each other’s local storage by using Cross Document Messaging API or window.name variable.
We have already seen examples of Cross Document Messaging API. Let’s see an example of bypassing Same Origin Policy using window.name variable.
http://www.qnimate.com/index.html
<script type="text/javascript">
window.document.getElementById("myFrame").src = "http://qnimate.com/navigate.html"; //navigating to parent origin so that it can access window name of frame
var localStorageData = window.document.getElementById("myFrame").contentWindow.name;
</script>
http://qscutter.com/localStorageData.php
window.name = localStorage.getItem("storedData");
script>
http://qnimate.com/navigate.html
You can learn more about use of window.name from these links. Link 1Link 2
Same Origin Policy for Cookies
Same Origin Policy for cookies works different. A page can set a cookie for its own domain or any parent domain.
For example;
www.qnimate.com can set a cookie for qnimate.com.
www.blog.qnimate.com can set cookies for blog.qnimate.com and qnimate.com.
blog.qnimate.com cannot set cookie for news.qnimate.com because news.qnimate.com is not a parent of blog.qnimate.com.
Note that a page cannot set cookie for public suffix. For example www.qnimate.com cannot set cookie for .com, .uk, .in etc.
The browser will make a cookie available to the given domain including any sub-domains.
For example;
A cookie of qnimate.com will be send to qnimate.com, www.qnimate.com and www.blog.qnimate.com.
Let’s see some code example:
http://www.qnimate.com
//if the leave the domain parameter blank then the default is www.qnimate.com
//this cookie will be available for blog.qnimate.com, www.qnimate.com, qnimate.com, www.blog.qnimate.com etc.
setcookie("cookiename", "cookievalue", "100000000", "\", "qnimate.com");
?>
http://www.qnimate.com
//this cookie will be reject by the browser as its been set for all domain with .com TLD (top level domain)
setcookie("cookiename", "cookievalue", "100000000", "\", "com");
?>
Extra Note: PHP automatically adds a ‘.’ in front of the domain name in the cookie. For older browser support of setting cookie for particular domains.
For example:
http://www.qnimate.com
setcookie("cookiename", "cookievalue", "100000000", "\", "qnimate.com");//www.qnimate.com will be replaced by .qnimate.com
setcookie("cookiename", "cookievalue", "100000000", "\");//www.qnimate.com will be replaced by .www.qnimate.com.
You can set Http-Only flags in cookies so that it cannot be accessed using JavaScript and you can also force a cookie to only be transmitted over a HTTPS connection. For example:
http://www.qnimate.com
No comments:
Post a Comment