浏览器同源策略
含义: 两个页面地址中的协议,域名,端口号保持一致,则表示同源
意义: 浏览器同源策略是浏览器的一个安全功能 分类:
(1)DOM同源策略:禁止对不同源页面的DOM进行操作。主要是Iframe跨域的情况,不同域名的iframe是限制互相访问的。 (2)XMLHttpRequest同源策略:禁止使用XHR对象向不同源的服务器地址发起HTTP请求。 来自一个源的js只能读写自己源的存储不能读写其他源的存储 存储包括,Cookies,Session Storage,Local Storage,Cache,Indexed DB等 来自一个源的js只能读取自己源的dom树不能读取其他源的dom树。如iframe内外层不同源就不能相互操作 一般而言来自一个源的js只能向自己源的接口发送请求不能向其他源的接口发送请求。 跨域问题解决办法
一,CORS
CORS(Cross-origin resource sharing,跨域资源共享) 含义:使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应式应该成功还是失败。只要服务器实现了CORS接口,就可以跨域通信。
CORS请求分类:简单请求和非简单请求
简单请求
请求方法是以下三种 HEAD GET POST HTTP的头部信息不超出以下几种字段 Accept Accept-Language Content-Language Last-Event-ID Content-type: 只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain 凡是不同时满足上面两个条件,就属于非简单请求。
处理流程
在请求中需要附加一个额外的 Origin 头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给予响应。例如:Origin:http://www.asdfg.cn 如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin中发回相同的源信息(如果是公共资源,可以回发 * )。例如:Access-Control-Allow-Origin:http://www.asdfg.cn 没有这个头部或者有这个头部但源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器会处理请求。注意,请求和响应都不包含 cookie 信息。 如果需要包含 cookie 信息,ajax 请求需要设置 xhr 的属性 withCredentials 为 true,服务器需要设置响应头部 Access-Control-Allow-Credentials: true 非简单请求
浏览器在发送真正的请求之前,会先发送一个 Preflight 请求给服务器,这种请求使用 OPTIONS 方法,发送下列头部:
Origin:与简单的请求相同。 Access-Control-Request-Method: 请求自身使用的方法。 Access-Control-Request-Headers: (可选)自定义的头部信息,多个头部以逗号分隔。 Origin: http://www.asdfg.cn Access-Control-Request-Method: POST Access-Control-Request-Headers: NCZ 发送这个请求后,服务器可以决定是否允许这种类型的请求。服务器通过在响应中发送如下头部与浏览器进行沟通:
Access-Control-Allow-Origin:与简单的请求相同。 Access-Control-Allow-Methods: 允许的方法,多个方法以逗号分隔。 Access-Control-Allow-Headers: 允许的头部,多个方法以逗号分隔。 Access-Control-Max-Age: 应该将这个 Preflight 请求缓存多长时间(以秒表示)。 Access-Control-Allow-Origin: http://www.asdfg.cn Access-Control-Allow-Methods: GET, POST Access-Control-Allow-Headers: NCZ Access-Control-Max-Age: 1728000 一旦服务器通过 Preflight 请求允许该请求之后,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样了。
二,JSONP 跨域
由于script标签不受浏览器同源策略的影响,允许跨域引用资源。因此可以通过动态创建script标签,然后利用 src 属性进行跨域,这也就是 JSONP 跨域的基本原理。
// 1. 定义一个 回调函数 handleResponse 用来接收返回的数据 function handleResponse(data) { console.log(data); };
// 2. 动态创建一个 script 标签,并且告诉后端回调函数名叫 handleResponse var body = document.getElementsByTagName('body')[0]; var script = document.gerElement('script'); script.src = 'http://www.laixiangran.cn/json?callback=handleResponse'; body.appendChild(script);
// 3. 通过 script.src 请求 http://www.laixiangran.cn/json?callback=handleResponse
,
// 4. 后端能够识别这样的 URL 格式并处理该请求,然后返回 handleResponse({"name": "laixiangran"}) 给浏览器
// 5. 浏览器在接收到 handleResponse({"name": "laixiangran"}) 之后立即执行 ,也就是执行 handleResponse 方法,获得后端返回的数据,这样就完成一次跨域请求了。
优点:使用简便,没有兼容性问题,目前最流行的一种跨域方法。
缺点:
只支持 GET 请求。 由于是从其它域中加载代码执行,因此如果其他域不安全,很可能会在响应中夹带一些恶意代码。 要确定 JSONP 请求是否失败并不容易。虽然 HTML5 给 script 标签新增了一个 onerror 事件处理程序,但是存在兼容性问题。 三,服务器代理。如nginx
← 网络协议 7层 5层 4层 ajax →