跨域问题嘛,总会遇到的,嘿嘿
虽然说浏览器的同源策略有效的隔离恶意文件,但是耐不住开发环境、测试环境、生产环境的地址存在不一样的可能性嘛
参考链接
跨域问题的原因
其实就是浏览器的同源策略导致了跨域的问题。
简单来说,同源其实就是"协议、域名、端口"相同才同源,即使指向统一 ip 地址的不同域名也是不同源的。
同源策略有效的防止了XSS、CSRF等攻击。
Allow-Control-Allow-Origin: *
chrome 的一个插件。
遇到过不好用的时候
Allows to you request any site with ajax from any source. Adds to response ‘Allow-Control-Allow-Origin: *‘ header
原理应该和 CORS 很像,就如介绍所言在 header 里添加了 Allow-Control-Allow-Origin: *
JSONP
<link href=''/>
<img src=''/>
<script src=''/>
↑ 这三个标签是允许跨域加载资源的。
而 JSONP 就是前端定义一个回调函数,使用 script 标签向某个不同源的地址请求数据,然后后台返回前端定义的这个函数,最后会运行这个函数,而函数的参数里带着请求的数据。
1 | // 定义 |
两个小缺点
- 仅支持 GET 方法
- 可能会遭受到 XSS 攻击
jsonp 与 ajax 的区别
虽然都是从客户端向服务端发送请求,但是 ajax 的核心是 XMLHttpRequet ,而 jsonp 的核心是 script 标签允许跨域请求,有点钻空子的感觉。
CORS
全称 Cross-origin resource sharing (跨域源资源共享),定义了在请求跨源资源时客户端和服务端如何沟通。
大概的思路就是使用自定的 HTTP header 让浏览器和服务器进行沟通,从而决定请求的成败。
CORS 请求被浏览器分为简单请求和复杂请求 。
简单请求
条件是使用的方法为 GET / POST / HEAD
且 header 的信息仅能有
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:值只限于 application/x-www-form-urlencoded、multipart/form-data、text/plain
大概的流程:
- 简单的 GET / POST 请求
- 发送时浏览器会自动附加一个额外的 origin header ,包含请求页面的源信息,就是协议、域名和端口
- 服务端根绝这个 origin header 判断是否响应,
- 若可以接受,则在返回的请求里的 Access-Control-Allow-Origin 里添加同源信息(公共信息则可以返回"*")
- 如果不存在这个 Access-Control-Allow-Origin 或者存在但是内容不匹配,则浏览器会驳回请求。
所以前端正常的发送请求就 ok 了
复杂请求
条件是使用的方法为 PUT / DELETE 或者有多余的 header 或 header 的 Content-Type 值为 application/json
复杂请求会在正式的通信前额外增加一个 HTTP 请求,称为 Preflighted Requests
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就报错。 – 跨域资源共享 CORS 详解
还是需要后端进行更多的支持。
如果需要在 HTTP 请求中携带 cookie ,则需要设置如下代码
1 | // 使用 ajax 时 |
Web Sockets
h5 的新协议,基于 TCP ,与 HTTP 兼容但是并不融入 HTTP ,目标是在一个单独的持久连接上提供双工、双向通信,建立成功后,服务端和客户端都能主动向对方接受/发送信息。
也就是所 ws 连接建立,除非某一方断开接连,服务端和客户端就一直保持通话状态。
但是建立连接还是要以来 HTTP 的,建立好之后就没 HTTP 什么事情了。
1 | // 需要填入绝对地址,同源策略对于 Web Sockets 并不适用 |
domain
之前在实习的时候使用了一次,而且还失败了(可恶
但是当时 ddl 快到了所以直接临时在后端换了一个中间件来解决跨域问题,没有深入了解 domain 解决跨域问题的原理。
使用 domain 来解决跨域的问题有(相比之下)较大的局限性,只能在二级域名相同的情况下使用,并且需要配合 frame 标签使用。
原理又是两个页面都通过 js 设置 document.domain 为基础主域,实现同域。
再两个二级域名相同的网页,比如 a.demo.com:3000/a.html 以及 b.demo.com:3000/b.html
1 | // a.html |