一、什么是跨域
跨域 (Cross-origin resource sharing, CORS) 是指在浏览器中,同源策略限制了来自不同域的脚本对每个网络资源的访问权限。
同源策略限制了一个网页脚本只能访问来自同一来源的网络资源。来源由协议,域名和端口号组成。如果协议,域名或端口不同,就视为不同的源。
跨域资源共享(CORS)是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个origin (domain)的web应用被准许访问来自不同源的指定的资源。
对于跨域请求,浏览器会在请求头中加入 Origin
字段,服务器根据这个字段来判断是否允许跨域访问。如果服务器允许,则在响应头中加入 Access-Control-Allow-Origin
字段。
对于简单请求(simple request),只会发送一个OPTIONS请求作为预检请求,询问服务器是否允许发送真正的请求。对于非简单请求(non-simple request),在发送真正的请求之前会先发送一个OPTIONS请求作为预检请求。
二、如何解决跨域问题
可以通过使用 JSONP ,CORS, 代理服务器 或者 WebSocket 等方式来解决跨域问题。
1、通过使用 JSONP
解决
JSONP (JSON with Padding) 是一种解决跨域问题的技术,它允许网页从不同源加载脚本。这样就可以通过动态创建 <script>
标签来加载并执行来自不同域名的 JavaScript。
具体来说,JSONP 使用了一个 callback
参数来告诉服务器应该返回一个 JavaScript 函数调用,而不是普通的 JSON 数据。
例如,如果想要请求一个名为 example.com
的网站的数据,可以这样实现:
function jsonpCallback(data) {
console.log(data);
}
var script = document.createElement('script');
script.src = 'http://www.baidu.com/data?callback=jsonpCallback';
document.body.appendChild(script);
服务器收到请求后,会返回一个 JavaScript 函数调用,如 jsonpCallback({"name":"value"})
。浏览器会把这个函数调用当作 JavaScript 代码执行,从而获取到服务器的数据。
在使用 JSONP 时,还需要注意几点:
- JSONP 只能用于发送 GET 请求,因此不能用于发送 POST、PUT、DELETE 等其他类型的请求。
- JSONP 不能设置请求头,因此不能用于认证或授权相关的请求。
- JSONP 需要服务器端配合才能工作,因此不能用于请求不支持 JSONP 的服务器。
- JSONP 可能会导致安全问题,因为它会在当前页面执行来自未知来源的代码。因此需要谨慎使用 JSONP,并对来自未知来源的数据进行验证。
由于以上限制,JSONP 已经被越来越少的人使用,越来越多的人使用 CORS 或者 WebSocket 等其他方法来解决跨域问题。
2、通过配置服务器端解决(即 CORS)
可以通过以下方式来解决跨域问题:
- 使用
Access-Control-Allow-Origin
头允许特定域名访问资源 - 使用
Access-Control-Allow-Credentials
头允许带上凭据(cookies)访问资源 - 使用
Access-Control-Allow-Methods
头允许特定的 HTTP 方法访问资源 - 使用
Access-Control-Allow-Headers
头允许特定的请求头访问资源 - 使用
Access-Control-Max-Age
头预检请求的有效期
这些方法都可以在服务器端配置,从而解决跨域问题。
需要注意的是,如果使用了 Access-Control-Allow-Origin
头来允许特定域名访问资源,那么当此值设为 *
时,所有域都能访问该资源,这可能会带来安全隐患,因此应该谨慎使用。
当浏览器发送跨域请求时,会先发送一个预检请求(OPTIONS),服务器收到预检请求后,会返回一些头信息,浏览器根据这些头信息来判断是否可以发送正式请求。
CORS 比 JSONP 更加灵活,支持所有类型的 HTTP 请求,并且可以设置请求头,因此越来越受欢迎。但是,CORS 依赖于浏览器的支持,而且需要在服务器端进行配置才能使用。
3、通过使用代理服务器解决
使用代理服务器也可以解决跨域问题,客户端向代理服务器发送请求,代理服务器再向目标服务器发送请求,并将目标服务器返回的结果返回给客户端。这样就可以避免浏览器的同源策略限制。
4、通过使用 WebSocket 解决
使用 WebSocket 也可以解决跨域问题,WebSocket 是 HTML5 中新增的一种在单个 TCP 连接上进行全双工通讯的协议。它的特点是建立在 TCP 上,而不是建立在 HTTP 之上,因此可以避免跨域限制。
总之,解决跨域问题有很多种方法,每种方法都有其优缺点,应该根据具体情况来选择最合适的方法。