A. 前端解决跨域都有哪些方法
什么是跨域?
浏览器发送的请求地址(URL)与所在页面的地址 不同(端口/协议/域名 其一不同)。简言之,浏览器发出的请求url,与其所在页面的url不一样。此时,同源策略会让浏览器拒收 服务器响应回来的数据,报错信息如下:
最常用的四种跨域解决方案
1.cors
cors跨域资源共享允许是在服务端"Access-Control-Allow-Origin"字段设置的,当将cors设置为允许某个地址访问时,该地址就可以跨域访问这个服务器地址。当cors设置为"*"时即允许所有地址访问时,则表示所有地址都可以跨域访问这个服务器地址的资源。
2、 通过jsonp跨域
Jsonp是Json的一种“使用模式”,他就可以解决浏览器遇到的跨域问题,我们可以动态创建script,再请求一个带参网址实现跨域通信。用Jsonp请求得到的是JavaScript,相当于直接用JavaScript解析。
3、postMessage跨域
在h5中新增了postMessage方法,postMessage可以实现跨文档消息传输,我们可以通过Windows的message事件来监听发送跨文档消息传输内容。
4、proxy(代理)
原理:因为同源策略只是针对浏览器的安全策略,但是服务端并不受同源策略的限制,也就不存在跨域的问题。
B. 手机APP和web服务端 跨域问题
跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。
在以前,前端和后端混杂在一起, 比如JavaScript直接调用同系统里面的一个Httphandler,就不存在跨域的问题,但是随着现代的这种多种客户端的流行,比如一个应用通常会有Web端,App端,以及WebApp端,各种客户端通常会使用同一套的后台处理逻辑,即API, 前后端分离的开发策略流行起来,前端只关注展现,通常使用JavaScript,后端处理逻辑和数据通常使用WebService来提供json数据。一般的前端页面和后端的WebService API通常部署在不同的服务器或者域名上。这样,通过ajax请求WebService的时候,就会出现同源策略的问题。
需要说明的是,同源策略是JavaScript里面的限制,其他的编程语言,比如在C#,Java或者iOS等其他语言中是可以调用外部的WebService,也就是说,如果开发Native应用,是不存在这个问题的,但是如果开发Web或者Html5如WebApp,通常使用JavaScript ajax对WebService发起请求然后解析返回的值,这样就可能存在跨域的问题。
一般的,很容易想到,将外部的资源搬到同一个域上就能解决同源策略的限制的。即在Web网站上同时开发一个Http服务端页面,所有JavaScript的请求都发到这个页面上来,这个页面在内部使用其他语言去调用外部的WebService。即添加一个代理层。这种方式可以解决问题,但是不够直接和高效。
目前,比较常见的跨域解决方案包括JSONP (JSON with padding)和CORS (Cross-origin resource sharing )。一些解决方案需要客户端和服务端配合如JSOP,一些则只需要服务端配合处理比如CORS。下面分别介绍这两种跨域方案,以及服务端WebService如何支持这两种跨域方案。
JSONP以及WebService的支持
同源策略下,某个服务器是无法获取到服务器以外的数据,但是html里面的img,iframe和script等标签是个例外,这些标签可以通过src属性请求到其他服务器上的数据。而JSONP就是通过script节点src调用跨域的请求。
当我们向服务器提交一个JSONP的请求时,我们给服务传了一个特殊的参数,告诉服务端要对结果特殊处理一下。这样服务端返回的数据就会进行一点包装,客户端就可以处理。
举个例子,服务端和客户端约定要传一个名为callback的参数来使用JSONP功能。比如请求的参数如下:
http://www.example.net/sample.aspx?callback=mycallback
如果没有后面的callback参数,即不使用JSONP的模式,该服务的返回结果可能是一个单纯的json字符串,比如:
{ foo : 'bar' }
如果和服务端约定jsonp格式,那么服务端就会处理callback的参数,将返回结果进行一下处理,比如处理成:
mycallback({ foo : 'bar' })
可以看到,这其实是一个函数调用,比如可以实现在页面定义一个名为mycallback的回调函数:
mycallback = function(data)
{
alert(data.foo);
};
现在,请求的返回值回去触发回调函数,这样就完了了跨域请求。
如果使用ServiceStack创建WebService的话,支持Jsonp方式的调用很简单,只需要在AppHost的Configure函数里面注册一下对响应结果进行过滤处理即可。
/// <summary>
/// Application specific configuration
/// This method should initialize any IoC resources utilized by your web service classes.
/// </summary>
/// <param name="container"></param>
public override void Configure(Container container)
{
ResponseFilters.Add((req, res, dto) =>
{
var func = req.QueryString.Get("callback");
if (!func.isNullOrEmpty())
{
res.AddHeader("Content-Type", ContentType.Html);
res.Write("<script type='text/javascript'>{0}({1});</script>"
.FormatWith(func, dto.ToJson()));
res.Close();
}
});
}
JSONP跨域方式比较方便,也支持各种较老的浏览器,但是缺点很明显,他只支持GET的方式提交,不支持其他Post的提交,Get方式对请求的参数长度有限制,在有些情况下可能不满足要求。所以下面就介绍一下CORS的跨域解决方案。
CORS跨域及WebService的支持
先来看一个例子,我们新建一个基本的html页面,在里面编写一个简单的是否支持跨域的小脚本,如下:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AJAX跨域请求测试</title>
</head>
<body>
<input type='button' value='开始测试' onclick='crossDomainRequest()' />
<div id="content"></div>
<script type="text/javascript">
//<![CDATA[
var xhr = new XMLHttpRequest();
var url = 'http://localhost:8078/json/ShopUserLogin';
function crossDomainRequest() {
document.getElementById("content").innerHTML = "开始……";
if (xhr) {
xhr.open('POST', url, true);
xhr.onreadystatechange = handler;
xhr.send();
} else {
document.getElementById("content").innerHTML = "不能创建 XMLHttpRequest";
}
}
function handler(evtXHR) {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var response = xhr.responseText;
document.getElementById("content").innerHTML = "结果:" + response;
} else {
document.getElementById("content").innerHTML = "不允许跨域请求。";
}
}
else {
document.getElementById("content").innerHTML += "<br/>执行状态 readyState:" + xhr.readyState;
}
}
//]]>
</script>
</body>
</html>
然后保存为本地html文件,可以看到,这个脚本中,对本地的服务http://localhost:1337/json/Hello 发起了一个请求, 如果使用chrome 直接打开,会看到输出的结果,不允许跨域请求。 在javascript控制台程序中同样可以看到错误提示:
那么如果在返回响应头header中注入Access-Control-Allow-Origin,这样浏览器检测到header中的Access-Control-Allow-Origin,则就可以跨域操作了。
同样,如果使用ServcieStack,在很多地方可以支持CORS的跨域方式。最简单的还是在AppHost的Configure函数里面直接写入:
/// <summary>
/// Application specific configuration
/// This method should initialize any IoC resources utilized by your web service classes.
/// </summary>
/// <param name="container"></param>
public override void Configure(Container container)
{
this.AddPlugin(new CorsFeature());
}
这样就可以了,相当于使用默认的CORS配置:
CorsFeature(allowedOrigins:"*",
allowedMethods:"GET, POST, PUT, DELETE, OPTIONS",
allowedHeaders:"Content-Type",
allowCredentials:false);
如果仅仅允许GET和POST的请求支持CORS,则只需要改为:
Plugins.Add(new CorsFeature(allowedMethods: "GET, POST"));
当然也可以在AppHost的Config里面设置全局的CORS,如下:
/// <summary>
/// Application specific configuration
/// This method should initialize any IoC resources utilized by your web service classes.
/// </summary>
/// <param name="container"></param>
public override void Configure(Container container)
{
base.SetConfig(new EndpointHostConfig
{
GlobalResponseHeaders = {
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
{ "Access-Control-Allow-Headers", "Content-Type" },
},
});
}
现在运行WebService,使用postman或者Chrome调用这个请求,可以看到返回的值头文件中,已经加上了响应头,并且可以正常显示返回结果了:
CORS使用起来简单,不需要客户端的额外处理,而且支持Post的方式提交请求,但是CORS的唯一一个缺点是对客户端的浏览器版本有要求,支持CORS的浏览器机器版本如下:
总结
本文介绍了JavaScript中的跨域基本概念和产生的原因,以及如何解决跨域的两种方法,一种是JSONP 一种是 CORS,在客户端Javascript调用服务端接口的时候,如果需要支持跨域的话,需要服务端支持。JSONP的方式就是服务端对返回的值进行回调函数包装,他的优点是支持众多的浏览器, 缺点是仅支持Get的方式对服务端请求。另一种主流的跨域方案是CORS,他仅需要服务端在返回数据的时候在相应头中加入标识信息。这种方式非常简便。唯一的缺点是需要浏览器的支持,一些较老的浏览器可能不支持CORS特性。
跨域支持是创建WebService时应该考虑的一个功能点,希望本文对您在这边面有所帮助,文中是使用ServiceStack来演示跨域支持的,如果您用的WCF的话,知道跨域原理的前提下,实现跨域应该不难。
参考资料:
https://github.com/ServiceStack/ServiceStack/wiki/Customize-HTTP-Responses
https://github.com/ServiceStack/ServiceStack/wiki/Request-and-response-filters
http://stackoverflow.com/questions/8211930/servicestack-rest-api-and-cors
http://stackoverflow.com/questions/15224038/rename-callback-parameter-for-jsonp
C. web前端跨域的一些解决方案
没有归纳之前对跨域的一些说法是模糊的,什么jsonp啊,跨域原理啊,心里只有一个大概的说法,知道这个东西,然后用的时候直接网络Ctrl+C,后来闲下来决定整理一波这些知识点,需知其所以然。
那么,其实这是浏览器对我们的一种保护机制,把坏人挡在门外。那么,问题来了,我们怎么确定门外的人到底是好人还是坏人呢?浏览器关上了坏人的一扇门,留给了我们好人一扇窗。
JSONP跟JSON没有关系..就好像JavaScript和Java一样
浏览器对script、img(这些标签的请求方式都是 GET ,所以jsonp不支持 POST )这种标签没有限制,我们就可以这样干
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
服务器端对于CORS的支持,主要就是通过设置 Access-Control-Allow-Origin 来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。 更多有关跨域资源共享 CORS 的知识
浏览器中可以查看对应的响应头,举个例子,如下
服务端允许CORS,服务端需要针对接口设置的一系列响应头 (Response Headers)
1.简单请求
目前大多数情况都采用这种方式。简单请求只需要设置 Access-Control-Allow-Origin 即可。满足以下两个条件,就属于简单请求。
2.非简单请求
非简单请求会发出一次预检测请求,返回码是204,预检测通过才会真正发出请求,这才返回200。来看栗子:
非简单请求需要根据不同情况配置不同的响应头,一系列响应头配置项见上方
这个说法相信不陌生,我们依然使用前端域名请求,然后有一个 中介商---代理 把这个请求转发到真正的后端域名上,那也就不存在跨域问题了。
比较普遍的Nginx,简单的配置一下就可以了。了解更多的配置信息: nginx详解
然后前端这边的请求地址是 http://localhost:9099/api/xxx ,然后Nginx监听到地址是 localhost:9099/api 的请求,就帮我们转发到真正的服务端地址 http://.com
CORS与JSONP的使用目的相同,但是比JSONP更强大。JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及在服务端同意jsonp方式时,可以向不支持CORS的网站请求数据。Nginx可以说是最方便的,不过需要部署Nginx才行,需要对服务器有一定的理解,不太适合刚入门的同学,当然也可以请后台同学帮忙部署。
window.postMessage(data,origin) 是 HTML5 的一个接口,专注实现不同窗口不同页面的跨域通讯。
现在是这么一个情况,由于同源策略的限制下, a.html 不能操作iframe( b.html )里面的dom,那么使用postMessage就可以解决这一情况
然后 b.html 页面通过message事件监听并接受消息:
这种方式只适合主域名相同,但子域名不同的iframe跨域。
比如主域名是 http://.com/:8888 ,子域名是 http://child..com/:8888 ,这种情况下给两个页面设置相同的document.domain即document.domain = .com 就可以访问各自的window对象了。
前端跨域整理
不要再问我跨域的问题了
D. 跨域问题解决方法
跨域?他是浏览器的 同源策略 造成的,是浏览器对javascript施加的安全限制。所谓同源是指:域名、协议、端口均相同。
解决
原理:利用标签具有可跨域的特性,可实现跨域访问接口,需要后端的支持。
服务器在收到请求后,解析参数,计算返还数据,输出messagetow(data)字符串。
缺点:只能发送get请求,无法访问服务器的响应文本(单向请求),即只能获取数据不能改数据。
通过ajax请求不同域的实现,底层不是靠XmlHttpRequest而是script,所以不要被这个方法给迷惑了。
在ajax请求中类型如果是type是get post,其实内部都只会用get,因为其跨域的原理就是用的动态加载script的src,所以我们只能把参数通过url的方式传递
其实jquery内部会转化成
http://192.168.31.137/train/test/jsonpthree?callback=messagetow
然后动态加载http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron">
http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron"><script type="text/javascript" src=" http://192.168.31.137/train/test/jsonpthree?callback=messagetow "></script>
http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron">
http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron">
Cross-Origin Resource Sharing(CORS)跨域资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,确保安全的跨域数据传输。现代浏览器使用CORS在API容器如XMLHttpRequest来减少HTTP请求的风险来源。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。服务器一般需要增加如下响应头的一种或几种:
跨域请求默认不会携带Cookie信息,如果需要携带,请配置下述参数:
window.name通过在iframe(一般动态创建i)中加载跨域HTML文件来起作用。然后,HTML文件将传递给请求者的字符串内容赋值给window.name。然后,请求者可以检索window.name值作为响应。
iframe标签的跨域能力;
window.name属性值在文档刷新后依旧存在的能力(且最大允许2M左右)。
每个iframe都有包裹它的window,而这个window是top window的子窗口。 contentWindow 属性返回<iframe>元素的Window对象。你可以使用这个Window对象来访问iframe的文档及其内部DOM。
HTML5新特性,可以用来向其他所有的 window 对象发送消息。需要注意的是我们必须要保证所有的脚本执行完才发送 MessageEvent,如果在函数执行的过程中调用了它,就会让后面的函数超时无法执行。
前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域,所以只能跨子域
在 根域 范围内,允许把domain属性的值设置为它的上一级域。例如,在”aaa.xxx.com”域内,可以把domain设置为 “xxx.com” 但不能设置为 “xxx.org” 或者”com”。
现在存在两个域名aaa.xxx.com和bbb.xxx.com。在aaa下嵌入bbb的页面,由于其document.name不一致,无法在aaa下操作bbb的js。可以在aaa和bbb下通过js将document.name = 'xxx.com';设置一致,来达到互相访问的作用。
WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很棒的实现。相关文章,请查看: WebSocket 、 WebSocket-SockJS
**需要注意:**WebSocket对象不支持DOM 2级事件侦听器,必须使用DOM 0级语法分别定义各个事件。
同源策略是针对浏览器端进行的限制,可以通过服务器端来解决该问题,例如nginx
DomainA客户端(浏览器) ==> DomainA服务器 ==> DomainB服务器 ==> DomainA客户端(浏览器)
E. 跨域是指什么,因为什么引起的有哪些解决方案web前端知识
广义跨域就是指跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容。由于安全原因,跨域访问是被各大浏览器所默认禁止的。
当一个域与其他域建立了信任关系后,2个域之间不但可以按需要相互进行管理,还可以跨网分配文件和打印机等设备资源,使不同的域之间实现网络资源的共享与管理。这就形成了“跨域”。
F. rust actix_web解决跨域问题
在做Web服务时使用的是与主站 配置的是fb.net , 另外个成员列表服务是 m1.fb.net ,这会造成一个跨域问题。在浏览器下使用 XML Http Request 或者 fetch 发出一个HTTP请求,假如这个HTTP的协议、主机名或者端口任意一个与当前网页地址有不一致时,为了安全浏览器会限制响应结果,通常这类问题就是所谓的跨域问题。
可以参考: https://segmentfault.com/a/1190000012550346
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
解决跨域问题的方式有很多,比如 jsonp , iframe 等等。但在这里,我使用HTTP协议里约定的字段来解决这个问题,这也是最干净完美的解决方案。为了处理有跨域请求的特殊场景,HTTP协议里有一个特殊的响应头字段 Access-Control-Allow-Origin ,意思允许访问的 Origin ,值可以是通配符 * ,允许所有,或者写上一个具体的 Origin 值。
在 actix-web 里, 我们需要配合 actix_cors 来处理关于跨域请求的配置,以下是一个例子
Cargo.toml
main.rs
测试一下
如果我们把Origin换成另一个域名,则会报错
400出错了,提示
不允许的Origin请求,另外http和https视为不同的origin,都需要添加支持。
如果你需要允许所有的 Origin ,也就是不做限制的话,那么使用 * 号做通配符
通常来说不建议这么干,
当然如果有nginx做负载的话,也可以在nginx上部署,此时后端服务可以不用如此实现了,否则可能会出现:
G. http网页建立websocket跨域问题,怎么解决
websocket是htm5提供的一种全双工通讯的协议。
websocket不存在跨域问题,html网页通过new Websocket(url,[protocol]);创建对象。
看你的提示应该是使用了ajax请求。
H. 怎么解决服务器间的跨域问题
跨域指的是浏览器的一种安全机制,服务器之间不存在跨域问题
如果两台服务器之间无法访问,请检查服务器的防火墙配置是否阻止了二者之间的通信
望采纳