Jsonp Sharing-cross-domain requests in JavaScript

Source: Internet
Author: User
Tags response code script tag

If you are developing a modern web-based application, then you:

    1. Use JavaScript on the client.
    2. Need to integrate services that are not completely under your control (or those from different domains).
    3. You have encountered this error message in your browser console:

XMLHttpRequest cannot load http://external.service/. No ' Access-control-allow-origin ' header is present on the requested resource. Origin 'Http://my.app' is therefore not allowed access.

I encounter this error every time I need to integrate a Web application with an external service that is not fully controlled or some server API. Google has not provided me with a concise description of the problem or an overview of the alternative to performing cross-domain requests, so this article will be used as a personal reference for the future.

Homologous policy

We encountered this problem because we violated the same-origin policy (SOP). This is a security measure implemented in the browser to restrict the interaction of documents (or scripts) between different sources.

The origin of a Web page is determined by its defined protocol, domain name, and port number. For example, the source of this page is (' http ', ' jvaneyck.wordpress.com ', 80). Resources with the same source can access each other completely. If page A and page B have the same source, JavaScript on page A can execute HTTP requests to page B's server, manipulate page B's DOM, and even read the cookies on page B. Note that the source is defined with the source address of the Web page. Clarification: JavaScript source files loaded from another domain (for example, jquery referenced from a remote CDN) will run in the source of the HTML page, which is the page containing the scrip, not the domain from which the JavaScript file came from.

For specific cross-domain HTTP requests, SOP prescribes the following general rules: Allow cross-domain write, prohibit read across domains. This means that if a and C are different sources, a sends an HTTP request that is correctly received by C (which is "write"), but the script in a will not be able to read any data-even the response code returned from C. This is the cross-domain "read" and is blocked by the browser, resulting in the above error. In other words,SOP does not prevent attackers from writing data to their source, it simply does not allow them to read data from your domain (cookies, localstorage or other) or to take advantage of responses received from their domain to do anything.

SOP is a very good thing to TM. It prevents malicious scripts from reading your domain's data and sending it to their servers. This means that some Scripting Guys will not be able to steal cookies so easily.

Performing cross-domain requests

However, sometimes you have to consciously perform cross-domain requests. Tip: This will require some extra work. Examples of legitimate cross-domain requests:

    • You must integrate third-party services (such as a forum) and have a rest API residing in different sources.
    • Server-side services are hosted in different (child) domains.
    • Client logic comes from different sources rather than server-side service endpoints.
    • 。。。

Depending on the number of controls you have on the server side, you have multiple options to enable cross-domain requests. I'll discuss possible solutions: JSONP, using server-side proxies and cors.

There are other options, the most widely used technology is the use of IFRAMEs and window.postmessage. I will not discuss this article again, but interested in these can click here.

Sample code

I have written some code to try different methods, which are discussed in this article. You can view the full code in our GitHub. They should be easy to run locally if you want to try it yourself. Each example has 2 sites, one site in the source (' http ', ' localhost ', 3000) Another in (' http ', ' localhost ', 3001). They are different sources, so 3000 request 3001 is considered a cross-domain request and is blocked by the browser by default.

Failed cross-domain requests

Consider the following scenario: A domain's page wants to perform a GET request to the page of domain B. This is what happens:

The browser sends the request to the server correctly:

GET / HTTP/1.1

The server returns a response:

HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8Content-Length: 57{"response": "This is data returned from the server"}

However, when the response is received, the browser mask response is further propagated and shows the homologous violation error as shown above. For example, if you use jquery, the Do () callback for a GET request will never be executed and you will not be able to read the data returned from the server.

JSONP

JavaScript Object Notation with Padding (abbreviated as JSONP) is a way to perform cross-domain requests that can be loaded from different domains by taking advantage of the script tag of an HTML page. Before we go into the details, I would like to say that it has some major problems:

    • JSONP can only be used to perform cross-domain get requests.
    • The server must explicitly support JSONP requests.
    • You must absolutely trust the server to provide the JSONP response.
    • If the server is compromised, JSONP can expose your site to a number of security breaches.

JSONP relies on the fact that:<script> tags can have resources from different domains. When the browser resolves the <script> tag, it will get the script content (from any source) and execute it in the current page. Typically, the server returns HTML or some data, such as XML or JSON, that is displayed as data format. When requesting a JSONP-enabled server, however, it returns a script block that executes a callback function that is specified in the page and provides the actual data as a parameter. In case your head explodes, the following example is more specific.

The source 3000 page wants to get the resources stored in source 3001. The Source 3000 page contains the following script tag:

<script     src= ' http://localhost:3001?callback=myCallbackFunction ' ></script>

When the browser resolves this script tag, it will normally issue a GET request:

GET /?callback=myCallbackFunction HTTP/1.1

Instead of returning the native JSON, the server returns a script block that contains a call to a function with the function name specified in the URL and the output data passed as a parameter.

http/1.1 okcontent-type:application/javascriptmycallbackfunction ({' Response ': ' Hello World from jsonp! '});

This script block is executed immediately after it is received by the browser. The function calls in the script block are evaluated on the current page. The current page defines a callback function that uses the returned data:

<script>    function  mycallbackfunction (data) {        $ (' body '). Text (data.response);    } </script>

Summarize:

    • Because the work of JSONP is obtained by a GET request by including a script tag (either plain HTML or programmatically), it only supports cross-domain HTTP GET requests. If you want to use other HTTP requests (like post, put, or delete), you cannot use the Jsonp method.
    • This method requires you to trust the server completely. This server may be compromised and returned to any code that will be executed on your page (thus allowing access to your website for cookies, localstorage, etc.). You can mitigate this danger by using frames and window.postmessage to perform cross-domain calls. For a concrete implementation of the method, you can view this example
Server-side Proxy

Another cross-domain request that bypasses the same-origin policy does not make any cross-domain requests! If you use a proxy that has your domain name, you can simply use it to access external services on the backend and return the results to your client code. Because the request code and the proxy are in the same domain, the same-origin policy is not violated.

This technique does not need to change the existing server-side code. It requires a server-side proxy service and also runs JavaScript code in the same domain as the browser.

For completeness, I present a short example:

Instead of executing a GET request directly to http://localhost:3001, we want to send the request to the proxy server for our domain.

GET /proxy?urlToFetch=http%3A%2F%2Flocalhost%3A3001 HTTP/1.1

The server performs the actual GET request for the external service. Server-side code can perform a cross-domain request normally without error, so it can be called successfully. The proxy service transports the results to the customer:

HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8{"response": "This is data returned from the server, proxy style!"}

Note that this approach also has some serious drawbacks. For example, we have not covered security-related topics in this article. If a third-party service uses cookies for serious identity, then you cannot use this method. Your own JavaScript code is a cookie that cannot access external domains, and cookies cannot be sent to your proxy service, so you cannot provide cookies that contain user credentials like third-party services.

CORS

You may be feeling a slight nausea. If you think the previous mechanism has a "hacky" flavor, then you are absolutely right. The previous method is to bypass the legitimate browser security mechanism and bypass it always has to write dirty.

Fortunately, there is a cleaner way: cross-origin Resource sharing (or cors).

Cors provides a mechanism for the server to tell the browser that domain a reads data from domain B is possible. It is done by including a new Access-control-allow-origin HTTP header in the response header. If you remember the introduction of the error message, this is exactly what the browser is trying to tell you. When the browser receives a cross-domain response, it checks the cors header. If the source specified in the response header matches the current source, it allows the Read access response. Otherwise, you will get nasty error messages.

A concrete example.

Request source 3000 as usual:

GET / HTTP/1.1

The source 3001 server checks whether the source can access the data, and adds an additional Access-control-allow-origin header to the response, listing the request Source:

HTTP/1.1 200 OKAccess-Control-Allow-Origin: http://localhost:3000Content-Type: application/json; charset=utf-8Content-Length: 62{"response": "This is data returned from the CORS server"}

When the browser receives a response, it compares the request source (3000) and the source (also 3000) that is listed in the Access-control-allow-origin header. Because they match, the browser allows the generation interpretation of source 3000 to perform the response.

As before, this approach has some limitations. For example, the older version of IE can only partially support cors. Also, in addition to the simplest requests for all requests, you must have double HTTP requests (refer to: preflighting CORS requests).

Summarize

In this article, I try to explain what types of requests are categorized as cross-domain requests and why they are blocked by the browser under the same-origin policy. In addition, I discussed several mechanisms for performing cross-domain requests. These mechanisms are summarized in the following table.

Mechanism Support for HTTP methods Server-Side modification requirements Note
JSONP GET Yes (Returns a script block containing the function call substitution element JSON) Need Full Trust server
Proxy All No (but your source requires an additional proxy component) The server backend executes the request, not the browser. May cause an issue with authentication
CORS All Yes (return additional HTTP headers) Older versions of IE are not supported. More "complex" requests that require additional HTTP calls (Preflighted requests)

As you can see, even the simplest cross-domain request does not have a silver bullet. If you have control of your server code and you do not need to support legacy browsers, I strongly recommend that you use the Cors method. As always, comment on your current needs and use the method that best suits you.

Translation: Cross-domain requests in Javascript

Translation is wrong in many places, please correct me.

Jsonp Sharing-cross-domain requests in JavaScript

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.