In-depth analysis on how Jsonp solves ajax cross-origin problems

Source: Internet
Author: User
Tags jquery cdn

In-depth analysis on how Jsonp solves ajax cross-origin problems

I. Introduction

Recently, there have been a lot of cross-origin problems, and I just saw this one. I just summarized that there are a lot of things about JSONP Baidu, and many people are copying others, in fact, there are just a few copies of the information. The key is that I still don't understand it. It may be a problem of ability. I have tried a lot. So I have summarized it and finally understood it. Note that Jsonp is used to solve the cross-origin issue of ajax. The actual implementation is not ajax.

1. same-origin policy

The browser has a very important concept-Same-Origin Policy ). The so-called same source means that the domain name, protocol, and port are the same. Client scripts (JavaScript and ActionScript) of different sources cannot read or write resources of the other party without explicit authorization.

2. JSONP

JSONP (JSON with Padding) is a "usage mode" of JSON, which can be used to solve cross-Origin data access problems in mainstream browsers. Because of the same-origin policy, web pages located in server1.example.com cannot communicate with servers that are not in server1.example.com, while HTML script elements are an exception. Using the open policy of the <script> element, the webpage can obtain JSON data dynamically generated from other sources. This usage mode is called JSONP. The information captured with JSONP is not JSON, but arbitrary JavaScript. It is executed with a JavaScript literal interpreter instead of a JSON parser.

Ii. Practice

1. Simulate cross-origin requests

If two tomcat servers are created on the local machine and the ports are 80, and 8888 respectively, different source conditions are met. If ajax is sent from one port to obtain data from another port, a cross-origin request problem is certainly reported.

Here there are two projects: jsonp (8080) and other (8888). In the jsonp project, index. jsp is as follows:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

In the other (8888) project, index. jsp is as follows: // because jsp is actually a servlet, jsp is used to represent servlet here.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

In fact, the above is nothing more than clicking the ajax button on the jsonp page to obtain data on the other page.

Result: chrome Console


XMLHttpRequest cannot load http: // localhost: 8888/other/index. jsp. no 'access-Control-Allow-origin' header is present on the requested resource. origin 'HTTP: // localhost: 100' is therefore not allowed access.

The above prompt indicates a cross-origin problem. You cannot access resources in the 8080 domain from the 8888 domain.

2. Use the script tag to access js files in the other domain

The <script> label src supports cross-origin requests. The most common application is the CDN service. For example, if jQuery is used in my project, but this js file does not exist, it takes a long time to download it, if you do not know the correct version, you can search for jquery cdn by Baidu. I can find one, for example, the cdn of bootstrap: keystore.

2.1 create a js/other. js file in the other root path,The content is as follows:

alert("this is other(8888) js");

2.2 Add the script tag to jsonp/index. jsp to introduce the js of other.

<script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script>

Go to http: // localhost: 8080/jsonp/index. jsp and alert will pop up immediately, indicating that the introduced js file is automatically executed and the Cross-origin request js is successful.

2.3 Similarly, direct reference will immediately execute alertIn other. write the function in js. Similarly, jsonp/index. it can also be called in jsp. This is not demonstrated. Most projects do this in development, and the pages are separated from js/css.

2.4 another note,If. in js, a function calls something in 8080 through ajax, and then calls this function after it is introduced. However, if other. the ajax function in js calls 8888. After the introduction, it is also called cross-origin.

3. Use a script to implement cross-origin requests

3.1 simple simulation server return data

Change jsonp/index. jsp to the following: note that the position of the introduced other. js is after the function getResult. If it is earlier, the system will prompt that the function does not exist. The js loading sequence is from the top. It was not created before the call and cannot be successful. Note that this refers to the introduced js file. If it is the same js file or the js on the current page, it is okay to execute the call and then write the function, however, if you execute the call to introduce the function in the js file and then introduce the js file, the system will prompt that the function does not exist.

<script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript">function jsonp_fun(){$.ajax({url:'http://localhost:8888/other/index.jsp',type:'post',dataType:'text',success:function(data){console.log(data);}});}function getResult(data){alert(data.result);}</script><script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script>

Then other. js

GetResult ({"result": "this is other domain's data "});

That is, in jsonp/index. compile the function on the jsp page, and then introduce the js input parameters of other domains to call this function. Here, you can first look at the parameters returned by the interfaces of other domain servers.

Refresh the page. The effect is of course

The alert box is displayed. this is other domain's data

3.2 simulate interface access

Do you still want to understand what js has done above and how it makes sense to transmit dead data ?, In fact, the src of the script can be connected not only to the js address, but also to the servlet address, that is, the http interface address. Therefore, you are too lazy to write the servlet. Here, you should write jsp as the interface, create other. jsp page with the following content:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%String params = request.getParameter("params");out.println("ajax cross success,the server receive params :"+params);%>

The content is very simple, that is, accepting a params parameter and then returning data to the caller.

In jsonp/index. jsp, add

<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script>

If you see this address, are you familiar with it? It turns out that you are stupid to use servlet. jsp is also a servlet. The process is that when the page is loaded, the script tag will send the request, then return the data. Refresh the page to see the effect.

Uncaught SyntaxError: Unexpected identifier

An error is reported. What is the problem with the code above? No. Click an error. You will see that the requested content is printed out. It means an error is prompted, indicating that the browser does not know the content, but the script does not actually know it.

Still do not understand, then you add the following content to the page, you see no error !! Yes

<script type="text/javascript">ajax cross success,the server receive params : jsonp_param</script>

So js cannot be parsed. Let's use another method. If we output a JSON string or the string that calls the current page function, it is similar to the getResult ({"result ": "this is other domain's data "});

Modify the content in other. jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%String params = request.getParameter("params");//out.println("ajax cross success,the server receive params :"+params);out.println("getResult({'result':'"+params+"'})");%>

Don't forget that we have defined jsonp/index. jsp in the past. After adding references, we still remember the order of the getResult function and the introduced function.

<script type="text/javascript">function getResult(data){alert(data.result);}</script><script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script>

Refresh the page and an announcement is made.

At this point, most of the Principles have been completed, and there is another problem. Here, the server returns getResult (xxx), where xxx can be treated as a lot of processing through the interface, and then the inserted value, however, how does the caller agree to the same name as the getResult function name on the other domain servers? Besides, many companies make their own services and developers of other companies call this function, does everyone go to the company to agree the name of the function to be called? How is it possible, so someone came up with a solution, of course not me ~~, It's actually quite easy, that is, it won't be enough to pass the callback function name together, so the code is as follows:

<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult"></script>

Other. jsp

<% @ Page language = "java" contentType = "text/html; charset = UTF-8" pageEncoding = "UTF-8" %> <% String params = request. getParameter ("params"); String callback = request. getParameter ("callback"); // after a series of operations on this interface, obtain the data and return the data to the caller String data = "{'result ': '"+ params +"'} "; out. println (callback + "(" + data + ")"); %>

The code is very simple, that is, passing the parameter name of a callback function. After a series of operations on this interface, the returned data is inserted into the callback function, and the called function gets the data of this interface, that is, like succsss: function (data) in ajax, and then processing data, the success callback function here is equivalent to the getResult function above. Of course, you can also write elegantly, for example:

function CreateScript(src) {$("<script><//script>").attr("src", src).appendTo("body")}function jsonp_fun(){CreateScript("http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult")}

4. Jquery's JSONP

So far, the principle of cross-origin requests has been clearly explained, but there is still a problem. I always think it is a bit strange to use this method. If jquery is used, the call will be very simple, in fact, the underlying implementation of jquery is also a script, and then specify the src method. Just like described above, jquery encapsulates it and looks more elegant, similar to the ajax call method, the Code is as follows:

<Script type = "text/javascript"> function getResult (data) {alert ("through jsonp, receive data from other domain:" + data. result);} function jsonp_fun () {$. ajax ({url: 'http: // localhost: 8888/other. jsp ', type: 'post', data: {'params': 'fromjsonp'}, ype: "jsonp", jsonp: "callback ", // The parameter name passed to the request handler or page to obtain the jsonp callback function name (generally the default value is callback) jsonpCallback: "getResult ", // The Custom jsonp callback function name. The default value is the random function name automatically generated by jQuery. You can also leave this parameter Unspecified. jQuery will automatically process the data for you. success: function (data) {}, error: function () {alert ('fail ');}});} </script> <body> <input type = "button" value = "jsonp" onclick = "jsonp_fun ()"/> </body>

In jsonCallback, the callback function is set to getResult. After the result is returned, the code in the getResult function is called first, and then the code in the success function is called. In general, the getResult function is not required, similarly, jsonCallback does not need to be set. Therefore, only the code in success is executed, which is also used like ajax in normal times.

The actual usage is as follows:

Function jsonp_fun () {$. ajax ({url: 'http: // localhost: 8888/other. jsp ', type: 'post', data: {'params': 'fromjsonp'}, ype: "jsonp", jsonp: "callback ", // The parameter name passed to the request handler or page to obtain the jsonp callback function name (generally the default value is callback) success: function (data) {alert ("through jsonp, receive data from other domain: "+ data. result) ;}, error: function () {alert ('fail ') ;}}}< % @ page language = "java" contentType = "text/html; charset = UTF-8 "pageEncoding =" UTF-8 "%> <% String params = request. getParameter ("params"); String callback = request. getParameter ("callback"); // after a series of operations on this interface, obtain the data and return the data to the caller String data = "{\" result \": \ "" + params + "\"} "; out. println (callback + "(" + data + ")"); %>

JsonpCallback is not specified here. In fact, a function name is assembled at the bottom layer of jquery. Of course, function generation rules are not studied.

Supplement:

1. ajax and jsonp are similar in calling methods, with the same purpose. They both request a url and process the data returned by the server, therefore, jquery and ext both use jsonp as a form of ajax encapsulation;

2. ajax and jsonp are essentially different. The core of ajax is to use XmlHttpRequest to obtain content not on this page, while the core of jsonp is to dynamically Add the <script> tag to call the js script provided by the server.

3. Therefore, in fact, the difference between ajax and jsonp is not whether to cross-origin. ajax can implement cross-origin through the server proxy, and jsonp itself does not reject data acquisition from the same domain.

4. Also, jsonp is a method or a non-mandatory protocol. Like ajax, jsonp does not have to transmit data in json format. If you want to, the string will work, however, this is not conducive to using jsonp to provide public services.

The above content is a small series of documents about how Jsonp solves ajax cross-origin problems. I hope to help you!

Related Article

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.