3 solutions for Spring Boot to solve cross-domain problems!

The separation of front and back ends is a general trend, and cross-domain issues are even more commonplace. Just use the title to go to Google or Baidu to find a large solution. Then why do you have to write it again? Don't rush to look down. Java Interview Collection PDF Full Version

Problem background:

Same Origin Policy, translated as "same origin policy". It is an important security metric for client-side scripts (especially JavaScript), and its purpose is to prevent a document or script from being loaded from multiple different "origins". It believes that trusted content loaded from any site is unsafe. When scripts that are dubious by browsers run in the sandbox, they should only be allowed to access resources from the same site, not those from other sites that may be malicious. Note: Having the same Origin means having the same protocol, host address and port. Once one of these three items of data is different, the resource will be considered to be obtained from a different Origin and will not be allowed to be accessed.

CORS was born to solve the SOP problem. Of course, CORS is not the only solution, but other solutions are not repeated here.


Introduction to CORS:

CORS is a W3C standard, the full name is "Cross-origin resource sharing" (Cross-origin resource sharing). It allows the browser to send an XMLHttpRequest request to a cross-origin (protocol + domain name + port) server, thereby overcoming the limitation that AJAX can only be used from the same source. CORS requires both browser and server support. Its communication process is done automatically by the browser without user involvement. For developers, CORS communication is no different from AJAX/Fetch communication of the same origin, and the code is exactly the same. Once the browser finds that the request is cross-origin, it will automatically add some additional header information, and sometimes an additional request will be made, but the user will not feel it. Therefore, the key to implementing CORS communication is the server. As long as the server implements the CORS interface, it can communicate across origins.

Browsers divide CORS requests into two categories: simple request and not-so-simple request.

The browser sends a simple CORS request, and only needs to add an Origin field in the header.

The browser sends a non-simple CORS request, and will add an OPTIONS query request before the formal communication, called a "preflight" request (preflight). The browser first asks the server whether the domain name of the current webpage is in the server's permission list, and which HTTP verbs and header fields can be used. The browser will send a formal XMLHttpRequest request only if it gets a positive answer, otherwise it will report an error.

Simple requests are HEAD, GET, POST requests, and the HTTP header information does not exceed the following fields Accept, Accept-Language, Content-Language, Last-Event-ID, Content-Type Note: Content-Type: limited to three Value application/x-www-form-urlencoded, multipart/form-data, text/plain

On the contrary, it is a non-simple request.

In fact, implementing CORS is very simple, that is, adding some response headers on the server side, and doing so is imperceptible to the front end and very convenient.

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 *, which means that requests for any domain name are accepted.

  • Access-Control-Allow-Methods This field is required. Its value is a specific string separated by commas or *, indicating all cross-domain request methods supported by the server. Note that all supported methods are returned, not just the method requested by the browser. This is to avoid multiple "preflight" requests.

  • Access-Control-Expose-Headers This field is optional. When requesting CORS, the getResponseHeader() method of the XMLHttpRequest object can only get 6 basic fields: Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, 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 to allow cookies to be sent. By default, no cookies occur, that is, false. For requests with special requirements on the server, for example, the request method is PUT or DELETE, or the type of the Content-Type field is application/json, this value can only be set to true. If the server does not want the browser to send cookies, just delete this field.

  • Access-Control-Max-Age This field is optional and used to specify the validity period of this pre-check request, in seconds. During the valid period, there is no need to issue another pre-inspection request.

By the way, if during development, it is found that there are two requests each time, one OPTIONS, one normal request, pay attention to each time, then you need to configure Access-Control-Max-Age to avoid issuing pre-checks every time request.

Solution:

The first method:

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 configured globally, and most of the solutions are on the Internet, but many of them are based on old spring versions, such as WebMvcConfigurerAdapter which has been marked as Deprecated in spring 5.0. 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 {}

For such outdated classes or methods, the authors of Spring will definitely explain the reasons in the annotations and tell you which new ones should be used. This is a very good coding habit, praise!

Spring5 supports at least jdk1.8, so the comments clearly indicate that you can directly implement the WebMvcConfigurer interface without using this adapter, because jdk1.8 supports default-method in the interface.

The second way:

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 method. The method is simple and clear. It is to write these response headers in the response. Many articles ask you to configure the first and second methods. In fact, this is not necessary, only You need one.

I'm also making complaints here, everyone's spirit of inexplicability.

The third method:

public class GoodsController {
@CrossOrigin(origins = "http://localhost:4000")
@GetMapping("goods-url")
public Response queryGoodsWithGoodsUrl(@RequestParam String goodsUrl) throws Exception {}
}  

That's right, @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 method, class, etc., similar to RequestMapping, that is, the methods under the entire controller can be controlled, or a single method can be controlled.

It can also be known that this is the smallest granularity cors control method, accurate to a single request level.


The above three methods can solve the problem, the most commonly used should be the first and second. It is sufficient to control the scope of several domain names of your own, and there is generally no need to make too much detail.

If these three configuration methods are used, who will take effect? ​​Similar to the style in css, the principle of proximity, see. Java Interview Collection PDF Full Version

Guess you like

Origin blog.51cto.com/14975073/2609715
Recommended