简体   繁体   English

JavaScript可以与其他服务器通信吗?

[英]Can JavaScript communicate to a different server?

Can JavaScript interact with a database that lives on a different server? JavaScript可以与位于不同服务器上的数据库进行交互吗?

Ie there are three computers involved 即,涉及三台计算机

  • A server : which gives an HTML page with JavaScript to 服务器:提供带有JavaScript的HTML页面
  • A client : which runs that page which wants to talk to 客户端:运行要与之交谈的页面
  • A second server : which sends and receives data to/from the client 第二个服务器:向/从客户端发送和接收数据

Does this violate the Same Origin Policy ? 这是否违反同源政策 If not why not? 如果不是为什么不呢? If so is there a way around it? 如果是这样的话还有办法吗?

My background - I'm a competent computer scientist but I've never dealt with client side programming. 我的背景 - 我是一位称职的计算机科学家,但我从未处理过客户端编程。 While answering feel free to use complex ideas but please assume I know nothing about the JavaScript language or the specific policies in place behind client-side programming. 虽然回答时可以随意使用复杂的想法,但请假设我对JavaScript语言或客户端编程背后的具体策略一无所知。

It does violate Same Origin whenever your html comes from server 1 and AJAX requests go to server 2. 当你的html来自服务器1并且AJAX请求转到服务器2时,它确实违反了同源。

Check out Cross Origin Resource Sharing . 查看跨源资源共享 It is a standard designed to handle exactly this situation. 它是一个旨在处理这种情况的标准。 It is implemented in most modern browsers. 它在大多数现代浏览器中实现。

Alternatively you can use JSONP to serve the data, or if you have no control of the second server, use a reverse proxy to proxy requests to the second server through the first. 或者,您可以使用JSONP来提供数据,或者如果您无法控制第二个服务器,请使用反向代理通过第一个服务器将请求代理到第二个服务器。

Yes, this violates the SOP. 是的,这违反了SOP。 There are ways round it, but it's worth underlining a key point: 有一些方法,但值得强调一个关键点:

Any attempt from the client to access a remote server requires complicity on the part of that server. 客户端访问远程服务器的任何尝试都需要该服务器的共谋。

So what are the options? 那有什么选择呢?

JSON-P JSON-P

JSON-P involves having the server return a response wrapped in an invocation to a callback function. JSON-P涉及让服务器将调用中包含的响应返回给回调函数。 It works like this: 它的工作原理如下:

  • a new script tag is DOM-scripted into the page, or an existing one is reused 新的脚本标记以DOM形式编写到页面中,或者重用现有的标记
  • the script tag's src attribute is set as the request path (script tags can load scripts from anywhere - they are not subject to the SOP) 脚本标记的src属性被设置为请求路径(脚本标记可以从任何地方加载脚本 - 它们不受SOP约束)
  • the server response with data, often (but not necessarily) encoded as JSON, and prints this out as an argument to an invocation of a callback function (which must be defined in your JS) 带有数据的服务器响应,通常(但不一定)编码为JSON,并将其作为参数打印出来,以调用回调函数(必须在JS中定义)

So a JSON-P request, written in native JS, looks like this: 因此,用本机JS编写的JSON-P请求如下所示:

callback = function(response) { console.log(response); };
var script = document.createElement('script');
script.src = 'http://www.some-request.com/here.php?callback=callback'; //the example happens to use the same name; the callback parameter tells the some-request domain what function to wrap JSON in 
document.body.appendChild(script);

Then, if the server's response was 然后,如果服务器的响应是

callback({"foo": "bar"});

...we'd get the response in our console. ...我们会在控制台中收到回复。 Note I explicitly make the function global because it must be accessible and not hidden by scope. 注意我明确地使函数成为全局函数,因为它必须是可访问的而不是由作用域隐藏。 (In this sense it must be globally accessible , but not necessarily global in the traditional sense - it could, for example, be a static method of a global namespace). (从这个意义上讲,它必须是全局可访问的 ,但在传统意义上不一定是全局的 - 例如,它可以是全局命名空间的静态方法)。

Many JSON-P-complying web servers allow you to stipulate the name of the function you want it to call, normally by appending this info to the request URL via &callback=func_name . 许多符合JSON-P标准的Web服务器允许您规定要调用的函数的名称,通常是通过&callback=func_name将此信息附加到请求URL。

More info on this here . 在此更多信息在这里

CORS / XHR2 CORS / XHR2

In CORS, aka the cross-domain idea behind XHR (ie AJAX) v2, this will mean the server sending a header signifying which domains may make cross-domain requests to it - or all domains. 在CORS中,也就是XHR(即AJAX)v2背后的跨域思想,这意味着服务器发送一个标题,表示哪些域可以向它发出跨域请求 - 或者所有域。 In PHP, for example, we could allow any caller domain to make the request thus: 例如,在PHP中,我们可以允许任何调用者域来发出请求:

header("Access-Control-Allow-Origin: *");

More info on this here . 在此更多信息在这里

EasyXDM* EasyXDM *

EasyXDM collates a number of vendor-specific and newer, HTML5-arriving means of posting and receiving text-based messages between domains, and is worth a look. EasyXDM整理了许多供应商特定的和更新的,HTML5到达的方式,在域之间发布和接收基于文本的消息,值得一看。

Non-JS 非JS

If you need to get something from a server that does not play ball, your only option is an intermediary server-side script, as these can fire cURL requests that can scrape a remote resource without the confines of the SOP. 如果您需要从不玩球的服务器获取内容,您唯一的选择是中间服务器端脚本,因为这些可以触发可以在没有SOP限制的情况下刮取远程资源的cURL请求。

$curl = curl_init("http://www.example.com/");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);

More on cURL here . 更多关于cURL的信息

Yes, this violates the same-origin policy. 是的,这违反了同源政策。

You can get around this limitation by using JSONP , which leverages the behavior of the script tag to grab data from the second (database) host. 您可以使用JSONP来解决此限制, JSONP利用script标记的行为从第二个(数据库)主机中获取数据。 This assumes that you can serve data from the second host in a very particular way: wrapping a JSON response in a callback. 这假设您可以以非常特殊的方式提供来自第二个主机的数据:在回调中包装JSON响应。 It also requires using GET to serve the responses. 它还需要使用GET来响应。

An alternative is CORS , which will also require some control over how the server is sending data, and will limit you to more recent web browsers. 另一种选择是CORS ,它还需要对服务器如何发送数据进行一些控制,并将限制您使用更新的Web浏览器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM