同源策略和CORS

github连接html

同源策略

从一个问题开始:node

为何表单提交没有跨域问题,但ajax提交有跨域问题?git

例子github

若是咱们向百度发起POST请求,会发现302失败了,不容许发POST请求。可是,若是发起Get请求,发现200成功了,记得点一下Preserve log , 在页面刷新和页面切换期间,勾选 ‘Preserve log’选项(在控制台上方)会保留控制台历史信息。除非你清除console或者关闭tab,不然信息将一直保留。也就是说,用表单向百度发起一个Get请求是没有任何问题的!!!虽然是2个不一样的域名!!!!面试

一样的请求若是用Ajax作一遍:ajax

虽然也是200成功了,可是log控制台却抛出一个错误:加载baidu.com失败了,是由于响应里面没有一个叫Access-Control-Allow-Origin的header所以不容许。理论上既然已经请求成功了,就因该响应一个html即百度的首页,可是响应是空白状态码是0是怎么回事?后端

这就是同源策略,若是不是baidu.com里的JS,就不能向baidu.com的域名发起Ajax请求api

只有协议+端口+域名 如出一辙才容许发Ajax请求(也就是让js调用XMLHttpRequest发起请求)跨域

如出一辙如出一辙如出一辙如出一辙如出一辙如出一辙如出一辙如出一辙如出一辙如出一辙浏览器

1.http://baidu.com能够向http://www,baidu.com发Ajax请求吗? yes/no 答案是:No

2.http:baidu.com:80能够向http://baidu.com:81发Ajax请求码? yes/no 答案是 No

www.baidu.com 和 baidu.com多是2个彻底不一样的网站,因此浏览器不能认为冒险,全部不容许在baidu.com里向www.baidu.com发Ajax请求

为何要用同源策略?

由于若是用form表单提交页面会刷新,以前的页面就会挂掉,挂掉的页面死无法拿到新的页面的内容的,因此浏览器会认为这是安全的。(只有aJax发的请求会受到同源策略的限制) 可是Ajax是能够读取响应内容的,由于浏览器是不少人在使用,若是容许读取别人的内容,若是能够访问支付宝的APi,是否是能够用Ajax发GEt请求首页的html,去找html里的余额读取别人的支付宝余额,用户毫无隐私可言,甚至能够访问QQ空间的照片留言等,因此浏览器必定要作一个安全限制,若是没有同源策略,就能够直接发起Get或者直接POST请求(能够POST能够直接转帐)

浏览器必须保证:只有协议+端口+域名如出一辙才容许发Ajax请求(也就是让js调用XMLHttpRequest发起请求),不然他就是一个很是危险的浏览器,形成隐私的泄露,这也是物联网的基础

若是实在是想请求那个域名呢?你能够和那个域名的后台打个电话,好比A是Tom.com的开发,B是Jack.com的开发,A想用AjaxGetB的内容,A就打电话对B说,让B告诉浏览器容许A去访问B,就能够了,那该怎么去实现呢?

在main.js里请求request.open('Get', 'http://jack.com:8002/xxx')

同时开启2个服务:node server.js 8001node server.js 8002

在浏览器里新开2个窗口:http://tom.com:8001http://jack.com:8002/

咱们会发如今tom的窗口里得不到请求的响应,由于不一样协议端口域名网站之间不容许发起Ajax请求,这也是同源策略的内容

Access to XMLHttpRequest at 'http://jack.com:8002/xxx' from origin 'http://tom.com:8001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
复制代码

在jack的窗口里发起的请求获得了响应

这时候tom同窗就会打电话给jack同窗,我要访问你的域名下的一个api叫/xxx(/xxx路径),有2中解决问题的办法

第一种是J经过SONP的方法(JSONP存在一个问题,因为JSONP是经过动态建立script来发请求的,因此它只能发Get请求不能发POST请求)

第二种是经过CORS的方法(通常用CORS的方法来解决跨域访问受同源策略限制)

CORS

CORS的全拼是Cross-origin resource sharing即“跨站资源共享”

CORS能够告诉浏览器,我俩一家的,别阻止他

Jack只须要在后端代码(server.js)加一句响应头:

response.setHeader('Access-Control-Allow-Origin',' http://tom.com:8001')
复制代码

若是把这里的http://tom.com:8001网址改成 * 号,就表示容许全部网站去访问

意思是:容许http://tom.com:8001这个域名get http://jack.com:8002/

这时候重启服务器以后,在tom的页面经过点击按钮向jack的网站发起一个get请求就会获得响应了,不会再受同源策略的限制了!!


总结

1.若是面试让手写Ajax。则

let request = new XMLHttpRequest()                      // 建立XMLHttpRequest对象
    request.open('Get', 'http://jack.com:8002/xxx')     //初始化它,配置request
    request.send()                                      // 发送它
    request.onreadystatechange = function () {          // 监听onreadystatechange
        if (request.readyState === 4) {                 //  判断readyState
            if (request.status >= 200 && request.status < 300) {// 判断request.status
                let string = request.responseText
                let obj = window.JSON.parse(string)
            } else if (request.status >= 400) {
                console.log('请求失败了')
            }
        }
    }
复制代码

2.用JS发起请求,再用jS处理响应就是Ajax

3.把XML进化成了JSON,JSOn是一个新的语言吧,它只支持JS的一部分语法,由于它抄袭了JS

4.Ajax有一个优势就是安全,由于它有同源策略。同源策略的内容是只有协议+端口+域名 如出一辙才容许发Ajax请求,若是不同,即便能发送成功可是拿不到响应的结果

5.若是向突破同源策略,该如何跨域呢?

突破同源策略 === 跨域 ===OCRS,CORS的内容就是告诉浏览器“他是我兄弟别阻止他去读取个人内容”,只须要在须要被访问的网站的后端加上一句话:

response.setHeader('Access-Control-Allow-Origin',' http://tom.com:8001')
复制代码
相关文章
相关标签/搜索