lemontreeshy 2019-06-25
一般情况下,XMLHttpRequest(XHR)对象只能访问与包含它的页面位于同一个域中的资源,这种安全策略可以预防某些恶意行为,即通常所说的同源策略。
只要协议、域名、端口号有任何一个不同,都会被当成不同的域。
下表给出了相对于 http://store.company.com/dir/... 同源检测的结果:
JSONP(JSON with padding)
JSONP由两部分组成:回调函数和数据。回调函数时当响应到来是应该在页面中调用的函数,名字一般在请求中指定。而数据就是传入回调函数中的JSON数据。
JSONP通过动态创建<script>标签来使用,script 的 src 属性不受同源策略的约束。
JSONP原理:
(1)首先在客户端注册一个callback, 然后把callback的名字传给服务器。
(2)此时,服务器先生成 json 数据。然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 。
(3)最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
(4)客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)
下面例子通过查询地理定位服务来显示IP地址及位置信息。
function handleResponse(res){ alert("You are at IP address" + res.ip + ",which is in" + res.city + ',' + res.region_name); } var script = document.createElement("script"); script.src = "http://freegeoip.net/json/?callback=handleResponse"; document.body.insertBefore(script,document.body.firstChild);
JSONP优点:兼容所有的浏览器
JSONP缺点:
1). JSONP 是从其他域中加载代码执行。如果其他域不安全,很可能会在响应中夹带一些恶意代码,而此时除了完全放弃 JSONP 调用之外,没有办法追究。
2). 要确定 JSONP 请求是否失败并不容易。如果动态脚本插入有效,就执行调用;如果无效,就静默失败。失败是没有任何提示的。
3). 只支持 get 请求。
如果Origin指定的源在许可范围内,服务器返回响应的头信息会增加如下几个字段:
Access-Control-Allow-Origin:必须, 表明可以同意哪些跨源请求,设置为*表明同意任意跨源请求
Access-Control-Allow-Credentials:可选,布尔值,表明服务器是否允许浏览器携带用户凭证相关信息,例如cookie、http认证等信息。CORS请求默认不发送Cookie和HTTP认证信息,如果要发送需要将 withCredentials属性设置为true。 如果服务器不返回该字段,即不允许,此时若浏览器发送了一个withCredentials属性为true的请求,则会被拒绝,在控制台报错。
非简单请求:
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight),询问当前网页所在的域名是否在服务器的许可名单之中,以及可以使用那些http方法及头信息字段。只有得到肯定的答复,浏览器才会正式发出XMLHTTPRequest请求。
预检请求使用的http方法是Options,表示这是个用来询问的请求。 http请求头中除了包含简单请求头中的origin字段,还包含几个特殊字段:
Access-Control-Request-Method:表明请求使用的HTTP方法
Access-Control-Request-Headers:用于在预先请求时,告知服务器要发起的跨域请求中会携带的请求头信息,是一个以逗号分隔的字符串
如果服务器确认允许跨源请求,则可以做出回应。
预检请求的回应除了简单请求的回应中的Access-Control-Allow-Origin字段外,还有几个特殊字段:
Access-Control-Allow-Methods:表明服务器支持的所有跨域请求的方法,返回所有可以避免多次预检请求
Access-Control-Allow-Headers:表明跨域资源可以携带的自定义表头列表
Access-Control-Max-Age:表明浏览器可以将相应结果进行缓存的时间(单位为秒),在缓存时间内可以不用重复发送预检请求
如果服务器否定了预检请求,会返回一个正常的HTTP相应,但是没有任何有关CORS的头信息字段。这时浏览器就会认定服务器不同意预检请求,会触发一个错误,在控制台报错.
只要服务器通过了预检请求,以后每次正常的CORS请求,就跟简单请求一样。
CORS优点:1. 相比于JSONP,不仅支持get请求,也支持post、put等请求。
CORS缺点: 1. 不是所有的浏览器都支持 2. 需要服务器支持
CORS浏览器兼容情况:
// 要创建 Web Socket,需要先实例一个 WebSocket 对象并传入服务器端的地址,必须为一个绝对URL: var socket = new WebSocket('ws://echo.websocket.org'); // 当浏览器和服务器连接成功后,会触发 open 事件 socket.onopen = function(evevt){ console.log('open'); } // 当服务器向客户端发来消息时,会触发 message 事件 socket.onmessage = function(event){ var data = event.data; // 返回的数据是字符串 console.log(data); } // 当浏览器收到服务器发送的关闭连接请求时,就会触发 close 事件 socket.onclose = function(event){ console.log('close'); } // 如果连接失败,发送、接收数据失败或者处理数据出现错误,会触发 error 事件 socket.onerror = function(event){ console.log('error'); } // 使用send方法像服务器发送数据(只能发送纯文本数据,复杂的数据结构需要JSON.stringify一下): socket.send("Hello World");
注:WebSocket对象不支持DOM2级事件侦听器,必须使用DOM0级事件语法。 **WebSocket缺点:** 1. 不是所有的服务器都支持 2. 必须有相应的服务器支持。 **WebSocket优点:**1. 支持实时通信,可以避免浏览器的短轮询及服务器的长轮询。 2. 长连接会带来一定的服务器内存开销 WebSocket浏览器兼容情况: