SpringBoot: Processing cross-domain requests

I. Cross-domain Background

1.1 What is cross-domain?

The general format of Url:

Protocol + Domain Name (Subdomain + Main Domain Name) + Port Number + Resource Address

Examples:

https://www.dustyblog.cn:8080/say/Hello

https + www + dustyblog.cn + 8080 + say/Hello
Form.

As long as one of the four components of protocol, sub-domain name, main domain name and port number is different, it can be considered as different domains. Different domains access each other's resources, which is called cross-domain.

1.2 A normal request

  • Controller layer code:
@RequestMapping("/demo")
@RestController
public class CorsTestController {

    @GetMapping("/sayHello")
    public String sayHello() {
        return "hello world !";
    }
}
  • Start the project, test the request

Browser Open localhost:8080/demo/sayHello

You can print out "hello world"

1.3 Cross-domain Testing

Take Chrome for example:

  • Open any website, such as: https://blog.csdn.net

  • Press F12, open the Developer Tool, in which the Console can directly enter the js code test;

var token= "LtSFVqKxvpS1nPARxS2lpUs2Q2IpGstidMrS8zMhNV3rT7RKnhLN6d2FFirkVEzVIeexgEHgI/PtnynGqjZlyGkJa4+zYIXxtDMoK/N+AB6wtsskYXereH3AR8kWErwIRvx+UOFveH3dgmdw1347SYjbL/ilGKX5xkoZCbfb1f0=,LZkg22zbNsUoHAgAUapeBn541X5OHUK7rLVNHsHWDM/BA4DCIP1f/3Bnu4GAElQU6cds/0fg9Li5cSPHe8pyhr1Ii/TNcUYxqHMf9bHyD6ugwOFTfvlmtp6RDopVrpG24RSjJbWy2kUOOjjk5uv6FUTmbrSTVoBEzAXYKZMM2m4=,R4QeD2psvrTr8tkBTjnnfUBw+YR4di+GToGjWYeR7qZk9hldUVLlZUsEEPWjtBpz+UURVmplIn5WM9Ge29ft5aS4oKDdPlIH8kWNIs9Y3r9TgH3MnSUTGrgayaNniY9Ji5wNZiZ9cE2CFzlxoyuZxOcSVfOxUw70ty0ukLVM/78=";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/demo/sayHello');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}
  • After input, press the Enter key directly to return the result:
Access to XMLHttpRequest at 'http://127.0.0.1:8080/demo/sayHello' 
from origin 'https://blog.csdn.net' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

The result shows that the request failed under https://blog.csdn.net domain name.

II. Solutions - Cors Cross-domain

2.1 What is Cors

CORS is called Cross Origin Resource Sharing (cross-domain resource sharing). Each page needs to return an http header named Access-Control-Allow-Origin to allow site access in foreign countries. You can only expose limited resources and limited site access in foreign countries.

We can understand that if a request needs to allow cross-domain access, it needs to set Access-Control-Allow-Origin in the http header to determine which sites need to be allowed to access. If hypothesis needs permission https://www.dustyblog.c The request for this site is cross-domain and can be set:

Access-Control-Allow-Origin:https://www.dustyblog.cn.

Solution 1: Use the @CrossOrigin annotation

2.2.1 Use the @CrossOrigin annotation on Controller

All interfaces under this class can be accessed across domains

@RequestMapping("/demo2")
@RestController
//@ CrossOrigin//All domain names have access to all interfaces under this class
@CrossOrigin("https://blog.csdn.net"// Only the specified domain name can access all interfaces under this class
public class CorsTest2Controller {

    @GetMapping("/sayHello")
    public String sayHello() {
        return "hello world --- 2";
    }
}

This specifies that all the methods in the current CorsTest2Controller can handle requests on the https://csdn.net domain. Here you can test:

  • stay https://blog.csdn.net The page opens the debugging window and enters (Note: The request address here is / demo2, please distinguish it from / demo in 1.2 case)
var token= "LtSFVqKxvpS1nPARxS2lpUs2Q2IpGstidMrS8zMhNV3rT7RKnhLN6d2FFirkVEzVIeexgEHgI/PtnynGqjZlyGkJa4+zYIXxtDMoK/N+AB6wtsskYXereH3AR8kWErwIRvx+UOFveH3dgmdw1347SYjbL/ilGKX5xkoZCbfb1f0=,LZkg22zbNsUoHAgAUapeBn541X5OHUK7rLVNHsHWDM/BA4DCIP1f/3Bnu4GAElQU6cds/0fg9Li5cSPHe8pyhr1Ii/TNcUYxqHMf9bHyD6ugwOFTfvlmtp6RDopVrpG24RSjJbWy2kUOOjjk5uv6FUTmbrSTVoBEzAXYKZMM2m4=,R4QeD2psvrTr8tkBTjnnfUBw+YR4di+GToGjWYeR7qZk9hldUVLlZUsEEPWjtBpz+UURVmplIn5WM9Ge29ft5aS4oKDdPlIH8kWNIs9Y3r9TgH3MnSUTGrgayaNniY9Ji5wNZiZ9cE2CFzlxoyuZxOcSVfOxUw70ty0ukLVM/78=";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/demo2/sayHello');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

Returns the result:

ƒ (e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}
VM156:8 hello world --- 2

Explain cross-domain success!

  • Change the domain name to test whether cross-domain is still valid. https://www.baidu.com Test it according to the above method and return the result:
OPTIONS http://127.0.0.1:8080/demo2/sayHello 403
(anonymous)
Access to XMLHttpRequest at 'http://127.0.0.1:8080/demo2/sayHello' 
from origin 'http://www.cnblogs.com' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

Explain cross-domain failure! It proves that this scheme has successfully designated some domain names that can be cross-domain!

2.3 Solution 2: CORS Global Configuration - Implementing WebMvc Configurer

  • New cross-domain configuration class: CorsConfig.java:
/**
 * Cross-domain configuration
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Bean
    public WebMvcConfigurer corsConfigurer()
    {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").
                        allowedOrigins("https://www.dustyblog.cn". //Allow cross-domain domain domain names, which can be expressed as * to allow any domain name to be used
                        allowedMethods("*"). //Allow any method (post, get, etc.)
                        allowedHeaders("*"). //Allow any request header
                        allowCredentials(true). //Bring cookie information
                        exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600) indicates that within 3600 seconds, the result can be cached without sending a pre-test request.
            }
        };
    }
}
  • Testing, in the domain name allowed to access https://www.dustyblog.cn/ Console input (note that the request here is http://127.0.0.1:8080/demo3):
var token= "LtSFVqKxvpS1nPARxS2lpUs2Q2IpGstidMrS8zMhNV3rT7RKnhLN6d2FFirkVEzVIeexgEHgI/PtnynGqjZlyGkJa4+zYIXxtDMoK/N+AB6wtsskYXereH3AR8kWErwIRvx+UOFveH3dgmdw1347SYjbL/ilGKX5xkoZCbfb1f0=,LZkg22zbNsUoHAgAUapeBn541X5OHUK7rLVNHsHWDM/BA4DCIP1f/3Bnu4GAElQU6cds/0fg9Li5cSPHe8pyhr1Ii/TNcUYxqHMf9bHyD6ugwOFTfvlmtp6RDopVrpG24RSjJbWy2kUOOjjk5uv6FUTmbrSTVoBEzAXYKZMM2m4=,R4QeD2psvrTr8tkBTjnnfUBw+YR4di+GToGjWYeR7qZk9hldUVLlZUsEEPWjtBpz+UURVmplIn5WM9Ge29ft5aS4oKDdPlIH8kWNIs9Y3r9TgH3MnSUTGrgayaNniY9Ji5wNZiZ9cE2CFzlxoyuZxOcSVfOxUw70ty0ukLVM/78=";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/demo3/sayHello');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

Output results

ƒ (e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}
VM433:8 hello world --- 3

Explain the success of cross-domain, change to another website such as https://www.baidu.com The test still shows cross-domain error prompt, which proves that the configuration is correct, and the scheme has passed the test.

2.3 Interceptor Implementation

Solve cross-domain problems by implementing the Fiter interface and adding headers to requests

@Component
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.addHeader("Access-Control-Allow-Credentials", "true");
        res.addHeader("Access-Control-Allow-Origin", "*");
        res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
        if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
            response.getWriter().println("ok");
            return;
        }
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

3. More

3.1 Source Address

Github sample code

Keywords: Java github

Added by ungovernable on Sun, 25 Aug 2019 13:31:38 +0300