什么是跨域问题?
跨域问题的产生,源自浏览器的同源策略:SOP
(Same origin policy)。
同源策略是由 Netscape
提出的一个著名的安全策略,它是浏览器最核心也是最基本的安全功能,所有支持 JavaScript
的浏览器都会使用这个策略,目的是为了保护本地数据不被 JavaScript
代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。
同源: 如果两个URL的协议、域名、端口号都相同,就称这两个URL同源
非同源限制:
- 无法读取非同源的
Cookie
、LocalStorage
和IndexedDB
- 无法接触非同源的
DOM
- 无法向非同源地址发送
AJAX
请求
跨域请求的解决方案
JSONP
Jsonp
(JSON with Padding
) 是一种非正式传输协议:允许用户传递一个 callback
参数给服务端,然后服务端返回数据时会将这个 callback
参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
在浏览器中,<script>
、<img>
、<iframe>
、<link>
等标签都可以跨域加载资源,而不受同源策略的限制。基于此原理,可以通过动态创建 script
,发送一个带 callback
参数的请求实现跨域通信。
使用 JS
动态生成 script
标签,进行跨域操作
function handler(response){console.log('The responsed data is: '+response.data)//处理获得的Json数据
}
var script = document.createElement('script')
script.src = 'http://www.example.com/?callback=handler'
document.body.insertBefore(script, document.body.firstChild)
或者直接添加:
<script src="http://www.example.com/?callback=handler"></script>
使用 jQuery
:
$.getJson('http://www.example.com/?callback=?',function(jsondata){ });
优点:简单适用,兼容性好(兼容低版本IE)。缺点:
- 只能接受
GET
请求,无法拿到相关的返回头,状态码等数据 - 安全问题(请求代码中可能存在安全隐患,callback参数恶意注入,可能会造成xss漏洞)
- 要确定
jsonp
请求是否失败并不容易,没有关于调用错误的处理
Nginx 代理
同源策略是浏览器的安全策略,不是 HTTP
协议的一部分。服务器端调用 HTTP
接口只是使用 HTTP
协议,不会执行 JS
脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过 nginx
配置一个代理服务器做跳板机,将前端的地址和后端的地址用 nginx
转发到同一个地址下,如 5500
端口和 3000
端口都转到 8080
端口下, 也可以解决跨域问题。
server {listen 8080;server_namelocalhost;location/ {add_header Access-Control-Allow-Origin 'http://localhost:5500' always;add_header Access-Control-Allow-Headers '*';add_header Access-Control-Allow-Methods '*';add_header Access-Control-Allow-Credentials 'true';if ($request_method = 'OPTIONS') {return 204;}proxy_passhttp://localhost:3000;}
}
CORS
CORS
(Cross-origin resource sharing)跨域资源共享,是一个 W3C
标准。它允许浏览器向跨源服务器,发出 XMLHttpRequest
请求,从而克服了 AJAX
只能同源使用的限制。
阮一峰