首先 什么是跨域
因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域,Ajax请求会失败。
那么是出于什么安全考虑才会引入这种机制呢?其实主要是用来防止CSRF攻击的。简单点说,CSRF 攻击是利用用户的登录态发起恶意请求。
也就是说,没有同源策略的情况下,A网站可以被任意其他来源的Ajax访问到内容。如果你当前A网站还存在登录态,那么对方就可以通过Ajax获得你的任何信息。当然跨域并不能完全阻止 CSRF 。
然后我们来考虑一个问题,请求跨域了,那么请求到底发出去没有?请求必然是发出去了,但是浏览器拦截了响应。你可能会疑问明明通过表单的方式可以发起跨域请求,为什么Ajax就不会。因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止 CSRF ,因为请求毕竟是发出去了。
那么我们来看一下JSONP是如何解决这个问题的:
JSONP的原理很简单,就是利用script标签没有跨域限制的漏洞。通过script标签指向一个需要访问的地址并提供一个回调函数来接收数据。
当需要通讯时:
<script src="http:/ / domain/api?param1=a¶m2=b&callback=jsonp"></script>
<script>
function jsonp(data) {
console.log(data)
}
</script>
JSONP使用简单且兼容性不错,但是只限于get请求。在开发中可能会遇到多个JSONP请求的回调函数名是相同的,这时候就需要自己封装一个JSONP ,以下是简单实现
function jsonp(url, jsonpCallback, success) {
let script = document.createElement ( 'script ' )script.src = url
script.async = true
script.type = 'text/ javascript'
window[jsonpCallback] = function(data) {
success && success( data)
}
document.body.appendChild ( script)
}
jsonp( 'http:/ / xxx ', 'callback ' , function(value) {
console.log( value)
})