Online various cross-domain tutorials, various practices, various questions and answers, in addition to the simple JSONP, many say that CORS is not feasible, always missing so one or two key configuration. This article only wants to solve the problem, all the code is hands-on.

This article addresses cross-domain get, POST, data, cookies, and so on.

This article will only talk about GET requests and POST requests. Please understand post requests as all kinds of requests other than GET requests.

JSONP

The principle behind JSONP is simple, taking advantage of the idea that there is no cross-domain problem when the front end requests static resources.

But only GET, only GET, only GET is supported.

Note that since this method is called JSONP, the backend data must use JSON data, not random string or other things, 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)); }});Copy the code

DataType: “json”. Other than this, the configuration is the same as normal requests.

Back-end SpringMVC configuration

If you also use SpringMVC, you can configure a JSONP Advice so that every Controller method we write doesn’t need to worry about whether the client is making a JSONP request, Spring will handle it automatically.

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
    public JsonpAdvice(){// If the request has a callback parameter, Spring knows it is a jSONp request."callback"); }}Copy the code

The above writing requirements
SpringMVC version no later than 3.2Anything below 3.2 I’d say it’s time to upgrade.

Back-end non-SpringMVC configuration

When I first started working, Struts2 was still very popular. Within a few years, SpringMVC basically dominated the domestic market.

Here’s a pseudocode to call the wrap method before our method returns to the front end:

public Object wrap(HttpServletRequest request){
    String callback = request.getParameter("callback");
    if(StringUtils.isBlank(callback)){
        return result;
    } else {
        return callback+"("+JSON.toJSONString(result)+")"; }}Copy the code

CORS

Cross-Origin Resource Sharing

After all, JSONP only supports GET requests, which certainly cannot meet all of our requests, so we need to move out CORS.

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

CORS supports the following browsers. At present, browser problems are 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

Let’s get straight to 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)// Return JSON data $("#response").val(JSON.stringify(response)); }});Copy the code

DataType: “JSON”, this is JSON, not JSONp, not JSONp, not jSONp.

CrossDomain: true, where cross-domain requests are used

XhrFields: {withCredentials: true}, so that the configuration can take cookies through, otherwise we would not be able to maintain sessions, many people are in this situation. Of course, if you don’t have this requirement, you don’t need to configure it.

Back-end SpringMVC configuration

For most Web projects, there are mVC-related configuration classes that inherit from the WebMvcConfigurerAdapter. If you are also using SpringMVC 4.2 or older, you can simply add this method as follows:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/ / * * *").allowedOrigins("*"); }}Copy the code

If you are unlucky enough to have a SpringMVC version lower than 4.2 in your project, you need to “save the country by the curve” :

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 * does not work, look down at 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); }}Copy the code

Configure filter in web. XML:

<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>
Copy the code

There are many projects that use Shiro, and you can also configure Shiro filters, which are not covered here.

Note that I’m talking about a very general configuration, which you can do for most projects. Article similar “*” this configuration readers should be able to know how to match.

Referer (Request.getheader (“referer”)) if the reader finds that the browser does not use the ‘*’ symbol, the reader can retrieve the referer (Request.getheader (“referer”)) in the request header in the filter above. Then dynamically set “access-Control-allow-origin” :

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"."*");
}
Copy the code

When the withCredentials in the front end are specified, the withCredentials in the front end should not be supported. True then the browser will say, well, one way to do this is to build origin dynamically, and the other way is to not pass cookies across domains, Let the front end put the cookie information (such as sessionId/accessKey) in the header or directly in the request parameters.

The front-end is not written in jQuery

The days of jQuery are over. Here’s how to solve the post cross-domain problem without using jQuery. Most OF the JS library will provide the corresponding scheme, we directly find the corresponding document to see how to use.

Here’s an introduction to native JS:

function createCORSRequest(method, url) {
    var xhr = new XMLHttpRequest();
    if ("withCredentials" inXHR) {// If you have the withCredentials attribute, you can be sure that it is an XMLHTTPRequest2 object. Look at the third parameter xhr.open(method, url,true);
    } else if(typeof XDomainRequest ! ="undefined"XHR = new XDomainRequest(); XHR = new XDomainRequest(); xhr.open(method, url); }else{// If so, unfortunately, browsers do not support CORS XHR = null; }return xhr;
}

var xhr = createCORSRequest('GET', url);
if(! xhr) { throw new Error('CORS not supported');
}
Copy the code

The “programmer friendly” browsers like Chrome, Firefox, Opera, and Safari use the XMLHTTPRequest2 object. Internet Explorer uses XDomainRequest.

I think that’s enough for 95% of you and I won’t go any further. If you have anything to add, please leave it in the comments section.

(Full text)