通信类

2018-12-10  本文已影响0人  陈裔松的技术博客

同源策略及限制

概念

同源策略限制从一个源加载的文档或脚本与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。

举例

以下网页想要访问以下接口,是不可以的。因为它们的源是不一样的。
网页:http://www.yourname.com/page1.html
接口:http://m.imooc.com/course/ajaxcourserecom?cid=459
设身处地的想一想,人家辛辛苦苦地做了一个信息库接口,结果被别的网页直接拿去调用了,是不是很过分?所以浏览器一定要有同源策略,以保证这种事情不会发生。

什么是源和跨域

源包括三部分内容,协议,域名和端口。
比如https://www.imooc.com,其中https是协议,www.imooc.com是域名,端口是80(如果没有指定端口,默认就是80)。这三部分共同组成了源,其中有一部分不一样,那么源就不一样的,也就是我们所说的跨域

什么是限制

不是一个源的文档,没有权利去操作另一个源的文档。
主要体现在以下几个方面:

可以跨域的三个标签(比较特殊)
跨域注意事项

Ajax相关

为什么要使用AJAX
如何创建Ajax(XMLHttpRequest)
// 第一步:创建一个XMLHttpRequest对象
var xhr = window.XMLHttpRequest ? (new XMLHttpRequest()) : (new ActiveXObject("Microsoft.XMLHTTP"));
// new ActiveXObject("Microsoft.XMLHTTP")是为了兼容老版本的IE浏览器(IE5 和 IE6)

// 第二步:调用open()方法启动一个请求以备发送
xhr.open("GET", "/api", false);
// 关于xhr.open(参数1,参数2,参数3)的说明
// 参数1:要发送的请求的类型(”get”、”post”等)
// 参数2:请求的URL
// 参数3:false(异步发送请求),true(同步发送请求)

// 第三步:绑定onreadystatechange事件以监听状态变化
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {  // 接收标准的HTTP状态码
            alert(xhr.responseText);
        }
    }
}
// 关于readyState说明
// 0 - (未初始化)未发送
// 1 - (启动)使用open()
// 2 - (载入)使用send()且执行完成,已经接受到全部响应内容
// 3 - (交互)正在解析响应内容
// 4 - (完成)响应内容解析完成,可以在客户端调用了

// 第四步:调用send()方法,分派请求到服务器
xhr.send(null);
// 关于xhr.send(params)的说明
// 调用send方法后才会发起请求
// params是指请求参数,如果不需要参数,则必须传入null,因为这个参数对有些浏览器来说是必需的。
// params除了字符串,还可以是复杂数据类型。
// ----比如这样--------------------------
// var formData = new FormData;
// formData.append('name':'123');
// xhr.send(formData);
// ------------------------------------------

注意1:IE低版本使用ActiveXObject,和W3C标准不一样
注意2:关于HTTP状态码,参考文章HTTP协议类 之 HTTP状态码

Ajax的其他方法和属性
// 终止一个ajax请求
// 请求已发出时,readyState会被置为0但不会触发readystatechange事件

xhr.send(formData);
console.log(xhr.readyState);  // 1

xhr.abort();
console.log(xhr.readyState);  // 0,ajax请求被终止,状态重置为0
// 设置请求头
// 多个同名字段存在时,多个值以逗号+空格连成一个
// 字段名忽略大小写
// 必须在open与send方法执行顺序中间调用
// 默认的Accept字段值为"*/*",接收所有类型的内容

xhr.open("GET", "/api", false);

xhr.setRequestHeader('user','imooc');    // 设置自定义请求头user的值为imooc
xhr.setRequestHeader('user','js');       // 设置自定义请求头user的值为js
// 以上设置了user两次,结果会合并成user: imooc, js

xhr.setRequestHeader('accept','text');   // 设置已有请求头accept的值为text,意思是接收text类型的内容

xhr.send(null);
// 获取响应头内容
// 参数接受响应头字段名,返回字段值
// 多个同名字段存在时,多个值以逗号+空格连成一个
// 字段名忽略大小写
xhr.getResponseHeader('accept');
// 设置请求的超时时间,单位为毫秒
// 超时后会触发timeout事件
// IE中,超时必须在open方法后,send方法前设置
xhr.open("GET", "/api", false);

xhr.timeout = 2000;  // 设置超时时间为2秒
xhr.ontimeout = function () {
    console.log("timeout!");
}

xhr.send(null);
// 返回一个XMLHTTPRequestUpload对象
// 可通过绑定事件侦听上传过程
// 设置响应内容的格式类型,默认字符串
// 可设置多种格式:json,blob,arraybuffer等
// 设置后会影响response的值

xhr.responseType = 'json';  // 设置responseType为json

xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            console.log(typeof xhr.response);  // Object
        }
    }
}
// 响应的正文内容
// 默认为字符串,但会被responseType影响

跨域通信

跨域通信的方式1:JSONP(前端)
<script>
    // 通过一个全局变量获取
    window.callback = function(data){
        // 这是我们得到的跨域信息
        console.log(data);
    }
</script>
<script src="http://coding.m.imooc.com/api.js"></script>
跨域通信的方式2:XHR2.0的CORS跨域方案(前端 + 服务器端)

CORS跨域方案中的前端请求,分为简单请求与复杂请求:

  1. 复杂请求会先发送一次OPTIONS方法的预检请求,而简单请求不需要预检
  2. 简单请求需要同时满足的条件:
    请求Method必须为HEAD,GET,POST之一
    请求头中的字段不超过Accept,Accept-Language,Content-Language,Last-Event-ID,Content-Type
    Content-Type只限于三个值application/x-www-form-urlencoded,multipart/form-data,text/plain

设置设置响应头(服务器端)

// 注意:不同后端语言的写法可能不一样

response.setHeader('Access-Control-Allow-Origin', 'http://a.com,http://b.com');
// 表示允许访问的域名,只允许设置一个。如果想设置多个,需要后端设置白名单并做判断。
// 必须在响应头中设置该字段
// 可使用 * 表示允许任意域名,但是不建议这么做

response.setHeader('Access-Control-Allow-Credentials','true');
// 值设置为true,表示允许向服务器发送cookie
// 客户端需要设置XHR对象的withCredentials为true
// Access-Control-Allow-Origin必须设置为指定域名,* 是不行的。

response.setHeader('Access-Control-Expose-Headers', 'Data');  // 允许客户端获取Data
// 表示允许客户端通过getResponseHeader方法获取的字段
// CORS方式下该方法默认只能获取6个基础字段
// Cache-Control,Expires,Content-Language
// Last-Modified,Content-type,Pragma


response.setHeader('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS');
// 表示服务端接受的跨域请求方法
// 多个方法用逗号分隔,使用 * 号表示任意方法
// 必须在预检响应头中设置该字段

response.setHeader('Access-Control-Allow-Headers', 'X-Requested-With');
// 表示服务端接受的跨域请求的字段
// 多个字段名用逗号分隔
// 请求头含Access-Control-Request-Headers时为必须

response.setHeader('Access-Control-Max-Age', '');
// 表示缓存预检结果
// 以秒为单位
// 在此期间不再发送预检请求
上一篇 下一篇

猜你喜欢

热点阅读