资讯专栏INFORMATION COLUMN

关于跨域

CoreDump / 774人阅读

摘要:经历了几场笔试面试,屡次被问到关于如何实现跨域。转自个人博客关于跨域什么是跨域一般来说,如果你在开发中需要进行跨域操作从一个非同源网站发送请求获取数据,一般而言,你在浏览器控制台看到的结果为同源策略说到跨域就不得不提同源策略。

前言

转眼就是秋招季啦。经历了几场笔试面试,屡次被问到关于如何实现跨域。老实说,之前都是纸上谈兵,也没有项目需要跨域,甚至觉得这个东西没什么意义。直到今天项目中遇到了跨域问题,看了不少资料才理解跨域的普遍性和意义。特写此篇文章整理自己所得。
转自个人博客: 关于跨域

什么是跨域

一般来说,如果你在开发中需要进行跨域操作(从一个非同源网站发送请求获取数据),一般而言,你在浏览器控制台看到的结果为:

XMLHttpRequest cannot load http://external-domain/service. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://my-domain’ is therefore not allowed access.

同源策略

说到跨域就不得不提“同源策略”。
同源策略是Web浏览器针对恶意的代码所进行的措施,为了防止世界被破坏,为了保护世界的和平,Web浏览器,采取了同源策略,只允许脚本读取和所属文档来源相同的窗口和文档的属性。
那么,怎么判断文档来源是否相同呢?很简单,看三个部分: 协议主机端口号。只要其中一个部分不同,则不同源。

跨域的应用场景

来自 home.example.com 的文档里的脚本读取 developer.example.com载入的文档的属性。

来自 home.example.com 的文档里的脚本读取 text.segmentfault.com载入的文档的属性

如何跨域 设置domain属性

针对上述应用场景的第一种情况,可以设置Document对象的domain属性。但是设置时使用的字符串必须具有有效的域前缀或者它本身。
PS: domain值中必须有一个点号。
PS: domain不能由松散的变为紧绷的。

//初始值 "home.example.com" 
document.domain = "example.com"; //OK
document.domain = "home.example.com"; //NO,不能由松散变紧绷
document.domain = "example"; //NO,必须有一个点号
document.domain = "another.com"; //NO, 必须是有效域前缀或其本身
JSONP

JSONP由两部分组成: 回调函数和数据。
原理:通过动态

某些API(例如Github API)允许你定义一个回调函数,当请求返回时执行该函数。

function logResults(json){
  console.log(json);
}

$.ajax({
  url: "https://api.github.com/users/jeresig",
  dataType: "jsonp",
  jsonpCallback: "logResults"
});

运行结果如下:

优点:

兼容性强。

简单易用,能之间访问响应文本,支持浏览器与服务器之间双向通信。

不足:

只能用GET方法,不能使用POST方法

无法判断请求是否失败,没有错误处理。

跨域资源共享CORS

需要浏览器和服务器同时支持。
原理:使用"Origin:"请求头和"Access-Control-Allow-Origin"响应头来扩展HTTP。其实就是利用新的HTTP头部来进行浏览器与服务器之间的沟通。

针对前端代码而言,变化的地方在于相对路径需改为绝对路径

//以前的方式
var xhr = new XMLHttpRequest(); 
xhr.open("GET", "/test", true); 
xhr.send(); 
//CORS方式
var xhr = new XMLHttpRequest(); 
xhr.open("GET", "http://segmentfault.com/test", true); 
xhr.send(); 

针对服务器代码而言,需要设置Access-Control-Allow-Origin,显式地列出源或使用通配符来匹配所有源。

优点:

CORS支持所有类型的HTTP请求。

使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据

不足:

不能发送和接收cookie
更新:服务端可以通过设置Access-Control-Allow-Credentials该字段来表示是否允许发送Cookie。发送ajax请求时,需配置withCredentials属性。(感谢sf小伙伴@lloyd_zhou 指正) 具体可查看 阮一峰大大的博客。

不能使用setRequestHeader()设置自定义头部

兼容IE10+

postMessage

postMessge()是HTML5新定义的通信机制。所有主流浏览器都已实现。该API定义在Window对象。

otherWindow.postMessage(message, targetOrigin);

message: 要传递的消息。
targetOrigin: 指定目标窗口的源。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;

当源匹配时,调用postMessage()方法时,目标窗口的Window对象会触发一个message事件。在进行监听事件时,应先判断origin属性,忽略来自未知源的消息。

//上的脚本:
var popup = window.open(...popup details...);
popup.postMessage("The user is "bob" and the password is "secret"",
              "https://secure.example.net");  
popup.postMessage("hello there!", "http://example.org");

function receiveMessage(event)
{
  if (event.origin !== "http://example.org")
    return;
  // event.source is popup
  // event.data is "hi there yourself!  the secret response is: rheeeeet!"【见下面一段代码可知】
}
window.addEventListener("message", receiveMessage, false);

针对上面的脚本进行接受数据的操作:

/*
 * popup的脚本,运行在:
 */

//当postMessage后触发的监听事件
function receiveMessage(event)
{
  //先判断源
  if (event.origin !== "http://example.com:8080")
    return;

  // event.source:window.opener
  // event.data:"hello there!"

  event.source.postMessage("hi there yourself!  the secret response " +
                           "is: rheeeeet!",
                           event.origin);
}

window.addEventListener("message", receiveMessage, false);
     
后续

收到了很多小伙伴的建议和指正,不胜感激,我会慢慢丰富这篇文章的内容的。请多多指教~

参考文章

前端跨域请求原理及实践

Window.postMessage()|MDN

老生常谈的跨域处理

JavaScript跨域问题总结

实现跨域的几种方式

jQuery’s JSONP Explained with Examples

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87910.html

相关文章

  • 关于跨域

    摘要:服务端接收到请求后,通过该参数获得回调函数名,并将数据放在参数中将其返回收到结果后因为是标签,所以浏览器会当做是脚本进行运行,从而达到跨域获取数据的目的。 在使用Vue搭建的一个后端管理系统中,我使用axios请求本地的Node环境下的接口,但是请求失败,然后我错误信息是:showImg(https://segmentfault.com/img/remote/1460000018521...

    AlexTuan 评论0 收藏0
  • 20K前端大佬面试(关于如何回答ajax跨域问题)

    摘要:在接触前端开发起,跨域这个词就一直以很高的频率在我们学习工作中重复出现,最近在工作中遇到了跨域的相关问题,这里我把它总结记录一下。 在接触前端开发起,跨域这个词就一直以很高的频率在我们学习工作中重复出现,最近在工作中遇到了跨域的相关问题,这里我把它总结记录一下。关于跨域,有N种类型,现在我只专注于ajax请求跨域(ajax跨域只是属于浏览器同源策略中的一部分,其它的这里不做介绍),内容...

    Yangyang 评论0 收藏0
  • 关于跨域踩的坑,浏览器 status code为200,但实际上是跨域

    摘要:背景后端使用并更改本地文件,起本地服务。使用调用后端接口,要求为格式,并要求在里加一些内容。借用凝雨关于跨域踩坑经验总结 背景 后端使用Nginx并更改本地host文件,起本地服务。将aaa.bbbb.com代理至本地IP地址(10.26.36.156)。使用$.ajax调用后端restful接口,要求content-type为application/json格式,并要求在reques...

    neu 评论0 收藏0
  • 关于vue-resource在dev环境下跨域问题的解决方法

    摘要:跨域问题相信跨域问题是每个前端在请求中都会遇到的问题因为浏览器的同源策略的限制所以是不支持跨域的当然当后台在没有完成搭建的时候这时候我们需要使用到模拟数据的时候这时候很多的就会出现跨域问题在中当然这个问题也不例外如下所以在此我也就整理出了 跨域问题 相信跨域问题是每个前端在ajax请求中都会遇到的问题,因为浏览器的同源策略的限制,所以ajax是不支持跨域的,当然当后台在没有完成搭建的...

    timger 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<