一、什么是跨域
了解跨域之前先了解同源策略。
同源策略:即浏览器为保障用户的安全,浏览器为了保证用户信息的安全,防止恶意的网站窃取数据,禁止不同域之间的JS进行交互。对于浏览器而言只要域名、协议、端口其中一个不同就会引发同源策略,从而限制他们之间如下的交互行为:
1、Cookie、LocalStorage 和 IndexDB 无法读取;
2、 DOM 无法获得;
3、 AJAX 请求不能发送。
只有协议、域名、端口都相同才是同域,否则就是跨域。
http://www.123.com/index.html 调用 | http://www.123.com/server.php (非跨域) |
http://www.123.com/index.html 调用 | http://www.456.com/server.php (主域名不同:123/456,跨域) |
http://abc.123.com/index.html 调用 | http://def.123.com/server.php (子域名不同:abc/def,跨域) |
http://www.123.com:8080/index.html 调用 | http://www.123.com:8081/server.php (端口不同:8080/8081,跨域) |
http://www.123.com/index.html 调用 | https://www.123.com/server.php (协议不同:http/https,跨域) |
二、如何解决跨域问题?
参考博客:https://blog.csdn.net/Joyhen/article/details/21631833
https://blog.csdn.net/Joyhen/article/details/21631833
(只分析常用的解决方法)
(一)Ajax跨域可以选择:
1、JSONP
JSONP由两部分组成,回调函数和数据。JSONP是被包含在函数调用中的JSON,如:callback({"name":"Judy"});
回调函授一般请求中指定,而数据就是传入回调函数中的JSON数据。
它的基本思想是,网页通过添加一个<script>
元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
首先,网页动态插入<script>
元素,由它向跨源网址发出请求。
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
上面代码通过动态添加<script>
元素,向服务器example.com
发出请求。注意,该请求的查询字符串有一个callback
参数,用来指定回调函数的名字,这对于JSONP是必需的。
服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。
foo({
"ip": "8.8.8.8"
});
由于<script>
元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo
函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因此避免了使用JSON.parse
的步骤。
2、CORC(跨域源资源共享 Cross-Origin Resource Sharing)
参考阮一峰老师的博客:http://www.ruanyifeng.com/blog/2016/04/cors.html
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
(与JSONP比较 :
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET
请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。)
3、Web Sockets
WebSocket是一种通信协议,使用ws://
(非加密)和wss://
(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
下面是一个例子,浏览器发出的WebSocket请求的头信息(摘自维基百科)。
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
上面代码中,有一个字段是Origin
,表示该请求的请求源(origin),即发自哪个域名。
正是因为有了Origin
这个字段,所以WebSocket才没有实行同源政策。因为服务器可以根据这个字段,判断是否许可本次通信。
(二)主域相同,处理多级子域之间的通信可以选择:
1、document.domain
(三)处理不同域之间的iframe,子窗口可以选择:
1、window.name
2、window.postMessage
3、location.hash
三、页面编码和被请求的资源编码如果不一致如何处理?
即前端请求和后端资源的编码不一致,对于 ajax 请求传递的参数,
如果是 get 请求方式,参数如果传递中文,在有些浏览器会乱码,不同的浏览器对参数编码的处理方式不同,所以对于 get 请求的参数需要使用 encodeURIComponent 函数对参数进行编码处理,后台开发语言都有相应的解码 api。
对于 post 请求不需要进行编码。
四、简述Ajax原理及请求过程