跨域总结

184 阅读3分钟

跨域问题产生的原因其实是浏览器的同源策略导致的,那也就是引出了怎么跨域的问题。主要的跨域方法是CORS和JSONP。

一、同源策略

同源策略简单来说是不同源的页面之间,不准相互访问数据。根据mdn的官方定义,同源策略是一个重要的安全策略,它用于限制一个的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介,从而保护用户隐私。

源是由协议、域名和端口号组成的,在控制台使用window.origin能够打印出当前网站的源。那么同源也就是协议、域名和端口号三者完全相同。像下面这种三者完成一致的就是同源的。

developer.mozilla.org:443/zh-CN/docs/…

developer.mozilla.org:443/en-US/docs/…

而下面则是不同源的,它们二者的域名不同。

[baidu.com:443](baidu.com:80(/)

www.baidu.com:443

这里实际上是为了突出端口号才写的端口,实际是http默认是80端口,而https默认是443端口,也就是说,www.baidu.com:443 完全等于www.baidu.com,默认端口可以省略。

二、CORS

两个不同的网站想要互相访问数据怎么办呢?可以使用CORS来做到。

Cross-Origin Resource Sharing(跨域资源共享)简称为CORS。跨域资源共享是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器「不同的域、协议或端口」请求一个资源时,资源会发起一个「跨域 HTTP 请求」。下面是我在服务器端模拟设置的让两个网站可以跨域的部分代码。主要是服务器端加上Access-Control-Allow-Origin的响应头。

else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://xinhai.com:9999')
    response.write(fs.readFileSync('./public/friends.json'))
    response.end()
}

可以在控制台中查看Access-Control-Allow-Origin响应头。

Access-Control-Allow-Origin响应头

具体的CORS语法可以参考MDN的具体介绍developer.mozilla.org/en-US/docs/…

三、JSONP

当某些版本较旧或者根本不支持CORS方案的浏览器需要跨域之时,我们可以使用JSONP来跨域。

同源策略虽然限制了数据的访问,但是我们可以引用JS,也就是script标签,通过script标签来请求资源,前端定义解析函数,并且声明执行函数;服务器端从callback参数得到那个执行函数并执行,之后就可以通过这个函数来获取数据了。这个函数就是一个回调函数。我们尝试封装一个简单的JSONP的部分代码。

function jsonp(url){
    return new Promise((resolve,reject)=>{
        const random = 'xinhaiJSONPCallback'+Math.random()
        window[random] = (data)=>{
            resolve(data)
        }
        const script = document.createElement('script')
        script.src = `${url}.js?callback=${random}`
        script.onload =()=>{
        script.remove()
        }
        script.onerror = ()=>{
            reject('加载失败')
        }
        document.body.appendChild(script)
    })
}

jsonp('http://qq.com:8888/friends.js')
    .then((data) =>{
        console.log(data)
    })

JSONP的优点是可以兼容一些不支持CORS的浏览器进行跨域,缺点为由于是script标签所以只支持GET,不支持POST;onload和onerror事件拿不到状态码。

重要参考:

1、10种跨域解决方案(附终极大招) - 掘金juejin.cn/post/684490…

2、浏览器的同源策略 - Web 安全 | MDN developer.mozilla.org/zh-CN/docs/…

3、Cross-Origin Resource Sharing (CORS) - HTTP | MDN developer.mozilla.org/en-US/docs/…