前端跨域的各种知识点
jsonp到底应该咋用啊.为了下次再遇到这种情况不至于很尴尬。今天,就来总结一下跨域的基本知识点。
1.为什么会发生跨域这种情况呢?
我们通常都是用ajax进行网络请求的。ajax的技术核心是XMLHttpRequest对象(简称XHR对象)。(既然都提到ajax了,不如复习下吧)
1.1 XHR的用法
1.1.1 同步请求
var xhr = createXHR()
xhr.open('get', 'example.php', false) // 参数:请求方式、请求地址、是否异步
xhr.send(null)
if((xhr.status > 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText)
} else {
alert('error')
}
open()方法并不会真正的发送请求。而知识启动一个请求以备发送。
send()方法接收一个参数,即要作为请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入null。调用send()方法之后,请求就会被分派到服务器。
在收到响应后,响应会自动填充XHR对象的属性。
responseText:响应的主体被返回的文本
responseXML: 如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存着响应数据的XML DOM文档。
status:响应的HTTP状态。(200:请求成功。304:请求的资源没有被修改。302:重定向。404:找不到路径。500:服务器报错)
statusText:HTTP状态的说明
1.1.2异步请求
异步请求,可以检测XHR的readyState属性。该属性表示请求/响应过程的当前活动阶段。
var xhr = createXHR();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if((xhr.status > 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText)
} else {
alert('error')
}
}
}
xhr.open('get', 'example.php', true)
xhr.send(null)
2.什么是跨域
跨域:同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。同源指:协议、域名、端口号必须一致。
同源策略控制了不同源之间的交互,例如在使用XMLHttpRequest 或 标签时则会受到同源策略的约束。这些交互通常分为三类:
- 通常允许跨域写操作(Cross-origin writes)。例如链接(links),重定向以及表单提交。特定少数的HTTP请求需要添加 preflight。
- 通常允许跨域资源嵌入(Cross-origin embedding)。
- 通常不允许跨域读操作(Cross-origin reads)。但常可以通过内嵌资源来巧妙的进行读取访问。例如可以读取嵌入图片的高度和宽度,调用内嵌脚本的方法,或availability of an embedded resource。
下面为允许跨域资源嵌入的示例,即一些不受同源策略影响的标签示例:
- <script src="..."></script>标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。
- <link rel="stylesheet" href="...">标签嵌入CSS。由于CSS的松散的语法规则,CSS的跨域需要一个设置正确的Content-Type消息头。不同浏览器有不同的限制: IE, Firefox, Chrome, Safari 和 Opera。
- <img>嵌入图片。支持的图片格式包括PNG,JPEG,GIF,BMP,SVG
- <video> 和 <audio>嵌入多媒体资源。
- <object>, <embed> 和 <applet>的插件。
- @font-face引入的字体。一些浏览器允许跨域字体( cross-origin fonts),一些需要同源字体(same-origin fonts)。
- <frame>和<iframe>载入的任何资源。站点可以使用X-Frame-Options消息头来阻止这种形式的跨域交互。
3.跨域的解决方法
下面是比较常用的解决跨域的方法。
3.1.1 jsonp
jsonp是利用动态添加script标签的形式,来进行跨域访问。因为script标签和img标签都有能力不受限制的从其他域加载资源。
jsonp由两部分组成:回调函数和数据(callback({name: 'xuying'}))
如果其他域不是特别安全,如果用jsonp进行跨域,则会有一些安全隐患。其次,要确定jsonp请求是否失败也并不容易。
3.1.2 CORS(跨域资源共享)
跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。
比如一个简单的get或者post请求,他没有自定义的头部,而主体内容应该是text/plain。在发送该请求时,需要给它附加一个额外的origin头部,其中包含请求页面的源信息(Origin: http://www.nnn.net),如果服务...,就在Access-Control-Allow-Origin头部中回发相同的源信息(如果是公共资源,可以回发'*')(Access-Control-Allow-Origin: http://www.nnn.net)
如果没有这个头部,或者有这个头部但源信息不匹配,浏览器都会驳回请求。ps:请求和响应都不包含cookie信息。
其他有关跨域的知识点,可以看这两篇博客:
掘金:https://juejin.im/post/5b5ff1...
github:https://github.com/Nealyang/Y...