由于同源策略,一般情况下,浏览器只允许本域下的接口交互。只要协议、域名、端口有任何一个不同,都被当作是不同的域,不同的域的网站之间发出资源请求时就叫跨域。
跨域的方式有
JSONP
JSONP(JSON with Padding)是资料格式 JSON 的一种“使用模式”,可以让网页从别的网域要资料。使用的原理是:script标签的src属性不受同源策略限制,可以跨域引用资源。
JSONP也叫填充式JSON,是应用JSON的一种新方法,只不过是被包含在函数调用中的JSON,例如:
callback({"name","trigkit4"});
JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的JSON数据。
参考例子:
网页端
<script>
var button = document.querySelector('#a')
var ul = document.querySelector('ul')
button.addEventListener('click',function (e) {
e.preventDefault()
var script = document.createElement('script')
//使用src引用外域资源,设置回调函数名
script.src = 'http://a.wfw.com:8080/jsonp?callback=test'
document.head.appendChild(script);
document.head.removeChild(script);
})
//定义处理返回数据的函数
var test = function (a) {
console.log(a)
}
</script>
</body>
模拟服务器端
router.get('/jsonp', function(req, res) {
// 获取回调函数名称
var name = req.query.callback
var note = '你好'
// 将数据设为回调函数的参数并返回
res.send(name + '(' + JSON.stringify(note) + ')')
})
CROS
CORS是跨域资源共享(Cross-Origin Resource Sharing),定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
参考例子:
网页端发出跨域Ajax请求
<script>
var button = document.querySelector('#a')
var ul = document.querySelector('ul')
button.addEventListener('click',function (e) {
e.preventDefault()
var xhr = new XMLHttpRequest()
xhr.open('get','http://a.wfw.com:8080/cors',true)
xhr.send()
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && (xhr.status == 200||xhr.status == 304)){
var data = JSON.parse(xhr.responseText)
var ss = document.createElement('li')
ss.innerText = data[0]
ul.appendChild(ss )
}
}
})
</script>
服务器端添加响应头信息
router.get('/cors', function(req, res) {
var note = ['你好']
// 添加响应信息
res.header("Access-Control-Allow-Origin", "http://localhost:8080")
res.send(note)
})
降域
当需要进行跨域的资源位于统一顶级域下时,可以更改它们的源来实现跨域访问。例如:a.wfw.com与b.wfw.com通过设置document.domain='wfw.com'来实现跨域访问
如:
\\url: http://a.wfw.com:8080/降域1.html
<input class="type" type="text" placeholder="http://a.wfw.com:8080/降域1.html">
<iframe src="http://b.wfw.com:8080/降域2.html" frameborder="0"></iframe>
<script>
document.querySelector('.type').addEventListener('input',function () {
console.log(this.value);
window.frames[0].document.querySelector('input').value = this.value;
})
document.domain = "wfw.com"
</script>
\\url: http://b.wfw.com:8080/降域2.html
<input class="type" type="text" placeholder="http://a.wfw.com:8080/降域2.html">
<script>
document.querySelector('.type').addEventListener('input', function(){
window.parent.document.querySelector('input').value = this.value;
})
document.domain = "wfw.com"
</script>