SpringBoot solves cross domain

SpringBoot solution cross domain, 3 solutions!

Problem background:

I have encountered cross domain problems in development and queried many solutions on the Internet. Here is a summary.

Introduction to CORS:

CORS is a W3C standard, The full name is "cross origin resource sharing". It allows the browser to send XMLHttpRequest requests to cross source (protocol + domain name + port) servers, thus overcoming the restriction that AJAX can only be used in the same source. CORS requires the support of both the browser and the server. Its communication process is completed automatically by the browser without user participation.

For developers, CORS communication is no different from the same source AJAX/Fetch communication, and the code is exactly the same. Once the browser finds that the request is cross source, it will automatically add some additional header information. Sometimes there will be one more additional request, but the user will not feel it. Therefore, the key to realize CORS communication is the server. As long as the server implements the CORS interface, it can communicate across sources.

The browser divides CORS requests into two categories: simple request and not so simple request.

When the browser sends a CORS simple request, it only needs to add an Origin field in the header information.

When the browser sends a CORS non simple request, it will add an OPTIONS query request before formal communication, It is called "preflight" request. The browser first asks the server whether the domain name of the current web page is in the server's license list, and what HTTP verbs and header information fields can be used. Only when you get a positive reply, the browser will send a formal XMLHttpRequest request, otherwise an error will be reported.

Simple requests are HEAD, GET and POST requests, and the HTTP header information does not exceed the following fields: Accept, Accept language, content language, last event ID and content type. Note: content type: only limited to three values application/x-www-form-urlencoded, multipart / form data and text/plain

On the contrary, it is not a simple request.

In fact, the implementation of CORS is very simple, that is, adding some response headers on the server, which is insensitive and convenient for the front end.

Detailed response header:

Access control allow Origin this field is required. Its value is either the specific value of the Origin field at the time of the request, or a *, indicating that the request for any domain name is accepted.

Access control allow methods this field is required. Its value is a comma separated concrete string or *, indicating all cross domain request methods supported by the server. Note that all supported methods are returned, not just the one requested by the browser. This is to avoid multiple "pre check" requests.

Access control expose headers this field is optional. During CORS request, the getResponseHeader() method of XMLHttpRequest object can only get six basic fields: cache control, content language, content type, Expires, last modified and Pragma. If you want to get other fields, you must specify them in access control expose headers.

Access control allow credentials this field is optional. Its value is a Boolean value indicating whether cookies are allowed to be sent By default, cookies do not occur, that is: false. For requests with special requirements for the server, for example, the request method is PUT or DELETE, or the type of content type field is application/json. This value can only be set to true. If the server does not want to send cookies to the browser, DELETE this field.

Access control Max age this field is optional. It is used to specify the validity period of this pre inspection request, in seconds. During the validity period, there is no need to issue another pre inspection request.

By the way, if you find that there are two requests each time during development, one OPTIONS and one normal request, please note that each time, you need to configure access control Max age to avoid sending pre check requests every time.

terms of settlement:

There are three solutions:

The first approach:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }
}

This method is globally configured, and most solutions are available online, but many are based on the old spring version, such as:

https://blog.csdn.net/tiangongkaiwu152368/article/details/81099169

In this paper, WebMvcConfigurerAdapter is implemented in spring 5 0 has been marked as Deprecated. Click the source code to see:

/**
 * An implementation of {@link WebMvcConfigurer} with empty methods allowing
 * subclasses to override only the methods they're interested in.
 *
 * @author Rossen Stoyanchev
 * @since 3.1
 * @deprecated as of 5.0 {@link WebMvcConfigurer} has default methods (made
 * possible by a Java 8 baseline) and can be implemented directly without the
 * need for this adapter
 */
@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {}

Spring 5 supports jdk1.0 as a minimum 8, so the comments clearly indicate that you can directly implement the WebMvcConfigurer interface without using this adapter, because jdk1 8. Default method exists in the support interface.

The second approach:

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "CorsFilter ")
@Configuration
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}

This method is based on the filter. The method is simple and clear. It is to write these response headers in the response. Many articles call you to configure the first and second methods. In fact, this is not necessary. Only one is needed.

The third approach:

public class GoodsController {
    @CrossOrigin(origins = "http://localhost:4000")
    @GetMapping("/test")
    public Response test(@RequestParam String param) throws Exception {}
}

Yes, it's the @ CrossOrigin annotation. Click to open the annotation

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {}

It can be seen from the meta annotation @ Target that annotations can be placed on methods, class es, etc., similar to RequestMapping, that is, the methods under the whole controller can be controlled, or a single method can be controlled.

It can also be seen that this is the minimum granularity cors control method, accurate to the single request level.

The above three methods can solve the problem. The most commonly used ones should be the first and second, (I suggest using the second) it is enough to control within the scope of several domain names. Generally, it is not necessary to be too detailed.

If these three configuration methods are used, who will take effect? Similar to the style in css and the proximity principle.

Keywords: Java Web Development Spring Boot

Added by tony-kidsdirect on Mon, 03 Jan 2022 08:24:55 +0200