jsonp-反向代理-CORS解决JS跨域问题的个人总结
jsonp-反向代理-CORS解决JS跨域问题的个人总结网上说了很多很多,但是看完之后还是很混乱,所以我自己重新总结一下。 解决 js 跨域问题一共有8种方法,
各个方法都有各自的优缺点,但是目前前端开发方面比较常用的是 jsonp,反向代理,CORS:
这里主要说明这三种方式。其他方式暂不说明。 一、什么是跨域问题跨域问题一般只出现在前端开发中使用 javascript 进行网络请求的时候,浏览器为了安全访问网络请求的数据而进行的限制。 提示的错误大致如下: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://XXXXXX' is therefore not allowed access.
二、为什么会出现跨域问题因为浏览器收到同源策略的限制,当前域名的js只能读取同域下的窗口属性。 2.1 同源策略同源指的是三个源头同时相同:
举例来说, 协议是 http:// 域名是 www.example.com 端口是80 //它的同源情况如下: http://www.example.com/dir2/other.html:同源 http://example.com/dir/other.html:不同源(域名不同) http://v2.www.example.com/dir/other.html:不同源(域名不同) http://www.example.com:81/dir/other.html:不同源(端口不同) 同源策略限制了以下行为:
大概可以知道跨域其实就是同源策略导致的,并且知道同源策略的原理。 详细的同源策略相关,可以参考http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html 三、解决跨域问题3.1 反向代理方式反向代理和正向代理的区别:
那么我们可以理解为反向代理 如何使用反向代理服务器来达到跨域问题解决:
现在前端开发一般使用 nodejs来做本地反向代理服务器 // 在 express 之后引入路由 var app = express(); var apiRoutes = express.Router(); app.use(bodyParser.urlencoded({extended:false})) // 自定义 api 路由 apiRoutes.get("/lyric",function (req,res) { var url = "https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg"; axios.get(url,{ headers: { // 修改 header referer: "https://c.y.qq.com/",host: "c.y.qq.com" },params: req.query }).then((response) => { var ret = response.data if (typeof ret === "string") { var reg = /^w+(({[^()]+}))$/; var matches = ret.match(reg); if (matches) { ret = JSON.parse(matches[1]) } } res.json(ret) }).catch((e) => { console.log(e) }) }); // 使用这个路由 app.use("/api",apiRoutes); 3.2 JSONP 方式JSONP有些文章会叫动态创建script,因为他确实是动态写入 script 标签的内容从而达到跨域的效果:
实现 jsonp 的方式:
引用来自http://www.52php.cn/article/p-pkpxwxvf-brm.html的图
这是一个实例 demo: 服务器端文件 foo({ "ip": "8.8.8.8" }); 客户端文件 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script> // 动态插入 script 标签到 html 中 function addScriptTag(src) { var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } // 获取 jsonp 文件 window.onload = function () { addScriptTag('http://example.com/ip?callback=foo'); } // 执行本地的 js 逻辑,这个要跟获取到的 jsonp 文件的函数要一致 function foo(data) { console.log('Your public IP address is: ' + data.ip); }; </script> </head> <body> </body> </html> 3.3 CORS 方式CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出
因此,实现CORS通信的关键是服务器端。只要服务器端实现了CORS接口,就可以跨源通信。 3.3.1 CORS的请求分为两类:
只要同时满足以下两大条件,就属于简单请求。 (1) 请求方法是以下三种方法之一:
(2)HTTP的头信息不超出以下几种字段:
凡是不同时满足上面两个条件,就属于非简单请求。 3.3.2 简单请求如果是简单请求的话,会自动在头信息之中,添加一个Origin字段 GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0... 这个Origin对应服务器端的 3.3.3 非简单请求如果是非简单请求的话,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。 浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。 需要注意这里是会发送2次请求,第一次是预检请求,第二次才是真正的请求! 首先发出预检请求: // 预检请求 OPTIONS /cors HTTP/1.1 Origin: http://api.bob.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Custom-Header Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0.. 除了Origin字段,"预检"请求的头信息包括两个特殊字段。 (1) 该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。 (2) 该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。 然后服务器收到"预检"请求以后: 检查了 // 预检请求的回应 HTTP/1.1 200 OK Date: Mon,01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Methods: GET,POST,PUT Access-Control-Allow-Headers: X-Custom-Header Content-Type: text/html; charset=utf-8 Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2,max=100 Connection: Keep-Alive Content-Type: text/plain 最后一旦服务器通过了"预检"请求: 以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。 // 以后的请求,就像拿到了通行证之后,就不需要再做预检请求了。 PUT /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com X-Custom-Header: value Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0... 详情参考这里http://www.ruanyifeng.com/blog/2016/04/cors.html 参考文档:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- C#仪器数据文件解析Excel文件的方法浅析(xls、x
- C#Web服务 – 返回然后最后 – 首先发生什么
- ruby-on-rails – Render:partial with:layout
- JsonCpp使用方法详解
- C语言经典算法 - 洗牌算法
- Vue DevTools调试工具的使用
- ruby-on-rails – 如何处理RestClient :: Server
- ruby-on-rails – 从Rails.application.routes.u
- ruby-on-rails – Rails显示belongs_to中的类别名
- flash – Vector map()如何在actionscript 3中运