12-SpringBoot Cross-domain Problem

1. Overview

1. What is Cross-Domain Request (CORS)

Cross-domain requests means that when a browser executes an ajax request for a script file, the service address of the script file is different from the service address requested.**To put it plainly, when the ip, network protocol and port are the same, they are the same domain, otherwise they are cross-domain.** This is due to Netscape's well-known security policy, Homology, which is a security restriction imposed by browsers on JavaScript.It is a measure to prevent scripts from maliciously attacking the server from outside the network.

2. Judging Cross-Domain

The same protocol, the same ip, the same port, one of the three different results in cross-domain.

The following are cross-domain requests:

Cross-domain problem description Example
Domain name is different Http://192.168.241.135andHttp://192.168.241.130
Ports are different http://192.168.241.135:8080 andHttp://192.168.241.135:80
Network protocols are different (https and http) Http://192.168.241.135andHttps://192.168.241.135

If the protocol, domain name, and port are all the same, but the request paths are different, this is not a cross-domain problem:

http://192.168.241.135/index and http://192.168.241.135/list

3. Cross-domain Solutions

Front End Solutions:

  1. Implement cross-domain calls using JSONP.
  2. Using NodeJS server as server proxy, the front-end sends requests to NodeJS server, and the NodeJS server proxy forwards requests to the back-end server.
  3. Setting up a browser allows cross-domain access, such as the Chrome browser settings--disable-web-security property, which is only applicable for development debugging in a development environment.

Backend solution:

  1. The server sets Acess-Control-Allow-Origin for Response Header (which can be set using Filter in development).
  2. Set up classes and methods that require cross-domain access to allow cross-domain access (such as using the @CrossOrigin annotation in Spring).
  3. Inherit CorsFilter using Spring Web (for Spring MVC, SpringBoot).
  4. Implement the WebMvcConfigurer interface (for SpringBoot).

2. Cross-domain configuration of Spring Boot

1. Configure using Filter

Use a Filter to Filter requests, and set the Acess-Control-Allow-Origin property declaration of the Rsponse Header (Response Header) to the requester to allow cross-domain access.

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter
public class CorsFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        //Set up all domain name access
        response.setHeader("Access-Control-Allow-Origin","*");
        //Set Send Cookie Information
        response.setHeader("Access-Control-Allow-Credentials","true");
        //Set which original domains are released (request mode)
        response.setHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS,DELETE");
        //Set the validity period for the specified pre-check request in seconds during which no further pre-check request will be issued
        response.setHeader("Access-Control-Max-Age","3600");
        //Set which original fields are released (header information)
        response.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept,cmreqeust,cnreqeust,token");
        filterChain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

Access-Control-Max-Age value description:

The browser's homology policy is to restrict cross-domain HTTP requests initiated from scripts for security reasons (e.g. asynchronous requests GET, POST, PUT, DELETE,OPTIONS, etc.), so the browser makes two requests to the requested server, the first one is that the browser initiates a preview request using the OPTIONS method, the second is really asynchronous, the first one is that the server knows whether to allow the cross-domain request: if allowed, the second real request is initiated; if not, the second request is interceptedRequest.

2. Configure with the @CrossOrigin annotation

Use the @CrossOrigin annotation to declare classes and methods to allow cross-domain access (added to Controller)

@RequestMapping("/user")
@RestController
@CrossOrigin
public class UserController {
    @Autowired
    private UserService userServiceImpl;

    @PostMapping("/getList")
    public Results getList(@RequestBody ListReqDto model){
        IPage<ExchangeCouponModel> list = userServiceImpl.getExchangeCouponList(model);
        Results results = Results.success(list);
        return results;
    }
}
3. Inherit using CorsFilter configuration in Spring Web
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;

@Component
public class CustomCorsFilter extends CorsFilter {
    public CustomCorsFilter(CorsConfigurationSource configSource) {
        super(configSource);
    }

    private static UrlBasedCorsConfigurationSource configurationSource(){
        CorsConfiguration config = new CorsConfiguration();
        //Set send cookie information
        config.setAllowCredentials(true);
        //Set up all domain name access
        config.addAllowedOrigin("*");
        //Set free those original domains
        config.addAllowedHeader("*");
        //Set the validity period for the specified pre-check request
        config.setMaxAge(3600L);
        //Set which original domains are released (request mode)
        config.setAllowedMethods(Arrays.asList("GET","POST","HEAD","PUT","DELETE","OPTIONS"));
        //Register CORS filter
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        //Configure Accessible Configurations
        source.registerCorsConfiguration("/*",config);
        return source;
    }
}
4. Implement WebMvcConfigurer interface

The WebMvcConfigurerAdaper class is obsolete in Springboot version 2.0 and can be implemented by implementing the WebConfigurer interface.

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 the interface provided by the parent class for cross-domain request processing
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //Add Mapping Path
        registry.addMapping("/**")
                //Release those original domains
                .allowedOrigins("http://127.0.0.1:8080")
                //Whether to send Cookie information
                .allowCredentials(true)
                //Which original domains are released (request method)
                .allowedMethods("GET","POST","DELETE","PUT")
                //Rest assured of which original domains (header information)
                .allowedHeaders("*")
                //Expose which header information (because cross-domain access does not get all header information by default)
                .exposedHeaders("header1")
                //Set the validity period for the specified pre-check request
                .maxAge(3600);
    }
}

Tags: Spring network SpringBoot Java

Posted on Thu, 11 Jun 2020 23:19:37 -0400 by chawezul