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 { } }