Various cross-domain tutorials, various practices, and various Q&A online. In addition to simple jsonp, many people say CORS are not working, and they always lack one or two key configurations. This article only wants to solve the problem, and all the code has been practiced by yourself.
This article solves problems such as get, post, data, and cookies in cross-domain.
This article will only talk about get requests and post requests. Readers should understand post requests as all other request methods except get requests.
JSONP
JSONP uses the principle that the browser has no homological restrictions on script resource references, and dynamically inserts a script tag, and will be executed immediately after the resource is loaded on the page. JSONP is an informal transmission protocol. One of the key points of this protocol is to allow users to pass a callback or define a callback method at the beginning, and the parameters are given to the server. When the server returns data, the callback parameter will be used as a function name to wrap the JSON data, so that the client can customize its own functions to automatically process the return data.
JSONP only supports GET requests but not other types of HTTP requests such as POST. It only supports cross-domain HTTP requests. It cannot solve the problem of how to make JavaScript calls between two pages in different domains. The advantage of JSONP is that it supports old-fashioned browsers, and the disadvantages are also obvious: it requires customization of the client and server for development. The data returned by the server cannot be standard Json data, but data wrapped by callback.
The principle of jsonp is very simple, and it uses the idea of [there is no cross-domain problem when the front-end requests static resources].
But it only supports get, only supports get, only supports get.
Note that since this method is called jsonp, the backend data must use json data. You cannot make a string or something casually, otherwise you will find the result inexplicable.
Front-end jQuery writing method
$.ajax({type: "get",url: baseUrl + "/jsonp/get",dataType: "jsonp",success: function(response) {$("#response").val(JSON.stringify(response));}});dataType: "jsonp". Except for this, other configurations are the same as normal requests.
Backend SpringMVC configuration
If you also use SpringMVC, then configure a jsonp Advice, so that every controller method we write does not need to consider whether the client is requesting jsonp, and Spring will automatically handle it accordingly.
@ControllerAdvicepublic class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice(){ // In this way, if the request contains the callback parameter, Spring will know that this is a jsonp request super("callback"); }}The above writing method requires that the SpringMVC version is not lower than 3.2, and I can only say that you should upgrade.
Backend non-SpringMVC configuration
When I first started working, Struts2 was still popular. After a few years, SpringMVC basically dominated the domestic market.
Be lazy, here is a pseudo-code, and click the wrap method before our method returns to the front end:
@ControllerAdvicepublic class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice(){ // In this way, if the request contains the callback parameter, Spring will know that this is a jsonp request super("callback"); }}CORS
Cross-Origin Resource Sharing
CORS is a way that modern browsers support cross-domain resource requests. The full name is "Cross-originresourcesharing". When sending a request using XMLHttpRequest, the browser finds that the request does not comply with the same-origin policy, and will add a request header to the request: Origin. The background performs a series of processing. If it is determined to accept the request, a response header is added to the return result: Access-Control-Allow-Origin; the browser determines whether the corresponding header contains the value of Origin. If there is, the browser will process the response, and we can get the response data. If the browser does not include the browser, we cannot get the response data.
CORS and JSONP use the same purpose, but it is more powerful than JSONP. CORS supports all browser request types, and the amount of requested data is larger and more open and concise. The server only needs to return the processed data directly, and there is no need for special processing.
After all, jsonp only supports get requests, which definitely cannot meet all our request needs, so CORS needs to be moved out.
Domestic web developers are still quite hard. Users do not upgrade their browsers, and the boss still wants developers to be compatible.
CORS supports the following browsers. At present, the browser's problems are becoming less and less important, and even Taobao does not support IE7~~~
Chrome 3+
Firefox 3.5+
Opera 12+
Safari 4+
Internet Explorer 8+
Front-end jQuery writing method
Just look 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", here is json, not jsonp, not jsonp, not jsonp.
crossDomain: true, here means using cross-domain requests
xhrFields: {withCredentials: true}, so that the configuration can bring the cookies, otherwise we can't even maintain the session, and many people are trapped here. Of course, if you don’t have this requirement, you don’t need to configure this.
Backend SpringMVC configuration
For most web projects, there are usually mvc-related configuration classes, which are inherited from WebMvcConfigurerAdapter. If you also use SpringMVC 4.2 or above, just add this method like the following:
@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**/*").allowedOrigins("*"); }}If you are unfortunately in your project, SpringMVC version is lower than 4.2, then you need to "save the country through curves":
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 the prompt * does not work, please look down on 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); }}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>
There are many projects that use shiro, and you can also configure shiro filters, so I won't introduce them here.
Note that I am talking about very general configurations, which can be configured in such general configurations for most projects. Readers should know how to match configurations like "*" in the article.
If the reader finds that the browser prompts that the '*' symbol cannot be used, then the reader can get the referer (request.getHeader("referer") in the request header according to the request object in the filter above, and 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", "*");}Front-end non-jQuery writing
The days when you eat jQuery with one trick are completely gone. Here I will talk about how to solve the problem of post cross-domain if you don’t use jQuery.
Let’s introduce a native js:
function createCORSRequest(method, url) { var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr) { // If there is the attribute withCredentials, it is definitely an XMLHTTPRequest2 object. Look at the third parameter xhr.open(method, url, true); } else if (typeof XDomainRequest != "undefined") { // This object is used by IE to request across domains xhr = new XDomainRequest(); xhr.open(method, url); } else { // If so, unfortunately, the browser does not support CORS xhr = null; } return xhr;} var xhr = createCORSRequest('GET', url); if (!xhr) { throw new Error('CORS not supported');}Among them, Chrome, Firefox, Opera, and Safari, these "programmer-friendly" browsers use XMLHTTPRequest2 objects. IE uses XDomainRequest.
Summarize
The above is all about quickly resolving cross-domain request issues: jsonp and CORS. I hope it will be helpful to everyone. Interested friends can continue to refer to other related topics on this site. If there are any shortcomings, please leave a message to point it out!