Quick resolution of cross domain request issues :jsonp and CORS

  • 2020-11-30 08:23:29
  • OfStack

All kinds of cross-domain tutorials, all kinds of practices, all kinds of q&A on the web, except simple jsonp, many of the CORS is not going to work, always missing one or two key configurations. This article only addresses the problem, and all the code is hands-on.

This article addresses cross-domain get, post, data, cookie, and so on.

This article will only talk about get requests and post requests, and readers should think of post requests as all requests other than get requests.

JSONP

JSONP makes use of the principle that the browser has no same-origin restriction on the resource reference of script, and dynamically inserts one script tag, which will be executed immediately after the resource is loaded into the page. JSONP transmission is a kind of informal agreement, the agreement of the 1 point is to allow users to transfer 1 callback or start to define a callback method, parameters to the server, then the server return data will be wrapped in this callback parameters as a function name to JSON data, so the client can customize their function to automatically deal with the data returned.

JSONP support GET request only and does not support POST and other types of HTTP request, it only supports cross-domain HTTP request this kind of circumstance, can't solve different domain between the two pages of problem, how to do JavaScript call JSONP advantage to support older browsers, obvious disadvantages: needs to be developed by the client and the server custom, the server returned data cannot be Json standard data, but data callback package.

The principle of jsonp is simple and takes advantage of the idea that there is no cross-domain problem when the front-end requests static resources.

But get only, get only, get only.

Note that 1, since this method is called jsonp, the backend data 1 must use json data, you can't just make a string or something, otherwise you will find the result confusing.

Front-end jQuery


$.ajax({
type: "get",
url: baseUrl + "/jsonp/get",
dataType: "jsonp",
success: function(response) {
$("#response").val(JSON.stringify(response));
}
});

dataType: "jsonp". Other than this, the other configurations are the same as normal requests.

Backend SpringMVC configuration

If you also use SpringMVC, then you can configure Advice of jsonp so that every Controller method we write does not need to consider whether the client is requesting jsonp or not, and Spring will automatically handle it accordingly.


@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
  public JsonpAdvice(){
    //  So if the request is taken  callback  Parameters, Spring  I know that this is  jsonp  The request of the 
    super("callback");
  }
}

SpringMVC version is required to be no less than 3.2. If it is lower than 3.2, I can only say that it is time for you to upgrade.

Non-SpringMVC backend configuration

When I first started working, Struts2 was popular all over the world. In a few years, SpringMVC basically ruled the domestic market.

1 lazy, paste a pseudocode here, before our method back to the front of the 1 wrap method:


@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
  public JsonpAdvice(){
    //  So if the request is taken  callback  Parameters, Spring  I know that this is  jsonp  The request of the 
    super("callback");
  }
}

CORS

Cross-Origin Resource Sharing

CORS is modern browsers support cross-domain resource request 1 way, full name is "cross-domain resource sharing" (Cross - originresourcesharing), when using XMLHttpRequest sends a request, the browser found that the request does not comply with the same origin policy, will give the request to add a request header: Origin, 1 series processing background, if determined to accept the request, add 1 response headers in return results: Access Control - Allow - Origin; The browser determines whether the corresponding header contains the value of Origin. If it does, the browser will process the response and we will get the response data. If it does not contain the response, the browser will reject it and we will not get the response data.

CORS is used for the same purpose as JSONP, but it is more powerful than JSONP. CORS supports all browser request types, carries a larger amount of request data, and is more open and concise. The server only needs to return the processed data directly, without any special processing.

After all, jsonp only supports get requests, which certainly cannot meet all our request needs, so we need to move out of CORS.

Domestic web developers are still more helpless and painful, users do not upgrade the browser, the boss also want developers to do compatibility.

CORS supports the following browsers. At present, browser issues are becoming less and less important, even Taobao does not support IE7 ~~~

Chrome 3+
Firefox 3.5+
Opera 12+
Safari 4+
Internet Explorer 8+
Front-end jQuery

Look directly at the code:


$.ajax({
  type: "POST",
  url: baseUrl + "/jsonp/post",
  dataType: 'json',
  crossDomain: true,
  xhrFields: {
    withCredentials: true
  },
  data: {
    name: "name_from_frontend"
  },
  success: function (response) {
    console.log(response)//  The returned  json  data 
    $("#response").val(JSON.stringify(response));
  }
});

dataType: "json", this is json, not jsonp, not jsonp, not jsonp.

crossDomain: true, which stands for using cross-domain requests

xhrFields: {withCredentials: true}, this configuration can bring cookie to the past, otherwise we can not even maintain session, many people are planted here. Of course, if you don't have this requirement, you don't need to configure this.

Backend SpringMVC configuration

For most web projects, general 1 will have mvc-related configuration classes, which inherit from WebMvcConfigurerAdapter. If you are also using SpringMVC 4.2 or above, simply add this method as follows:


@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
 
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**/*").allowedOrigins("*");
  }
}

If unfortunately the SpringMVC version of your project is below 4.2, then you need to "curve save the Country" 1:


public class CrossDomainFilter extends OncePerRequestFilter {
  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    response.addHeader("Access-Control-Allow-Origin", "*");//  If you are prompted  *  No, please look down 
    response.addHeader("Access-Control-Allow-Credentials", "true");
    response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
    response.addHeader("Access-Control-Allow-Headers", "Content-Type");
    filterChain.doFilter(request, response);
  }
}

In ES171en. xml configuration filter:


<filter>
  <filter-name>CrossDomainFilter</filter-name>
  <filter-class>com.javadoop.filters.CrossDomainFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CrossDomainFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

There are many projects using shiro, or by configuring the shiro filter, which I won't cover here.

Note that I'm talking about general configuration, which is what you can do for most projects. The reader should know how to match a configuration like "*" in this article.

If the reader finds that the '*' symbol cannot be used, the reader can take the referer (request.getHeader (" referer ") in the request header from the filter object above and dynamically set "ES189en-ES190en-ES191en-ES192en" :


String referer = request.getHeader("referer");
if (StringUtils.isNotBlank(referer)) {
  URL url = new URL(referer);
  String origin = url.getProtocol() + "://" + url.getHost();
  response.addHeader("Access-Control-Allow-Origin", origin);
} else {
  response.addHeader("Access-Control-Allow-Origin", "*");
}

Front-end is not jQuery

The days of jQuery are all but gone, so here's how to solve the cross-domain problem of post without using jQuery.

Let's take a look at native js:


function createCORSRequest(method, url) {
  var xhr = new XMLHttpRequest();
  if ("withCredentials" in xhr) {
    //  If you have  withCredentials  This property, then it must be  XMLHTTPRequest2  Object. Look at the first 3 A parameter 
    xhr.open(method, url, true);
  } else if (typeof XDomainRequest != "undefined") {
    //  This object is  IE  Used for cross-domain requests 
    xhr = new XDomainRequest();
    xhr.open(method, url);
  } else {
    //  If so, unfortunately, the browser does not support it  CORS
    xhr = null;
  }
  return xhr;
}
 
var xhr = createCORSRequest('GET', url);
if (!xhr) {
  throw new Error('CORS not supported');
}

Among them, Chrome, Firefox, Opera, Safari -- "programmer friendly" browsers -- use XMLHTTPRequest2 objects. IE USES XDomainRequest.

conclusion

That's the end of this article on quick resolution of the cross-domain request problem :jsonp and CORS, and I hope you'll find it helpful. Interested friends can continue to refer to other relevant topics in this site, if there is any deficiency, welcome to leave a message!


Related articles: