Original blog: pjmike’s blog

CORS is introduced

Cross-domain resource sharing has always been a hot need, and we can use CORS to quickly implement cross-domain access with only authorization on the server side and no additional setup on the front end

To put it simply, CORS is a kind of access mechanism, English full name: cross-origin Resource Sharing, that is, we say cross-domain Resource Sharing. When a resource requests a resource from a different domain or port than the server on which the resource itself resides, the resource makes a cross-domain HTTP request. For example, in a web page under one domain name, call resources in another domain name.

How CORS works

The XMLHttpRequest object is created by a simple request (usually a GET/POST/HEAD request, without adding any additional request headers). Non-simple requests (those that have special requirements on the server, such as a PUT or DELETE request method, or a Content-Type field of Type Application/JSON) require a “precheck” request to be sent before the server approves the cross-domain access request.

A simple request

The following analysis is extracted from ruan Yifeng’s detailed explanation of cross-domain resource sharing CORS

For simple requests (GET/POST/HEAD), the browser simply issues a CORS request, specifically by adding an Origin field to the header. As shown below:

GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-language: en-us Connection: Keep alive - the user-agent: Mozilla / 5.0...Copy the code

The Origin field indicates the source (protocol + domain + port) from which the request came. Based on this value, the server decides whether to approve the request or not.

If Origin specifies a source that is not covered by the license, the server will return a normal HTTP response. When the browser realizes that the response header does not contain the Access-Control-Allow-Origin field, it knows it is wrong and throws an error that is caught by the ONError callback of XMLHttpRequest.

If Origin specifies a domain name within the license, the server returns a response with several additional header fields

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
Copy the code

Let’s summarize the request and response headers for simple requests related to CORS

Request Headers

  • Origin: indicates the original domain of the cross-domain request

Response Headers

  • Access-Control-Allow-Origin: indicates which primitive domains are allowed to be accessed across domains. Its value is either when requestedOriginThe value of the field, or one*To accept requests from any domain name
  • Access-control-allow-credentials: Indicates whether clients are allowed to send cookies. It is a Boolean value. By default, cookies are not included in CORS requests, and true indicates explicit permission from the server to include cookies in the request and send them to the server
  • Access-Control-Expose-Headers: of the XMLHttpRequest object when CORS requests itgetResponseHeader()If you want to retrieve a custom header field, you need to retrieve a custom header fieldAccess-Control-Expose-HeadersSpecify the inside

Non-simple request

For CORS requests that are not simple requests, an HTTP query request is added before formal communication, called a “precheck” request. Here is the HTTP header for a precheck request:

OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
Copy the code

In addition to the Origin field, there are two special fields:

  • Access-control-request-method: Used to list HTTP methods used by browser CORS requests
  • Access-control-request-headers: This field is a comma-separated string that specifies the additional Header field to be sent by a browser CORS Request. X-custom-header is used in this example

Response to precheck request

After receiving the precheck request, the server responds:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
Copy the code

The following is a summary of the CORS related headers in response to the precheck request:

  • Access-control-allow-methods: comma-separated string indicating all Methods supported by the server for cross-domain requests. Note that this is all methods, not the same method as a single browser request, to avoid multiple “precheck” requests
  • Access-Control-Allow-Headers: If the browser request includesAccess-Control-Request-HeadersField,Access-Control-Allow-HeadersIs required to indicate all header information fields supported by the server, not limited to those requested in the browser represearch
  • Access-control-max-age: Specifies the validity period of the precheck request, in seconds. This field is optional.

How to implement CORS cross-domain request

For cross-domain requests of CORS, there are mainly the following options:

  • Returns a new CorsFilter
  • Rewrite WebMvcConfigurer
  • Using annotations@CrossOrigin
  • Manually set the response header (HttpServletResponse)

Note:

  • CorFilter/WebMvConfigurer / @Crossorigin requires SpringMVC 4.2 or later, which corresponds to springBoot 1.3 or later
  • The first two attributes belong to global CORS configurations, while the last two attributes belong to local CORS configurations. Local cross-domain rules override global cross-domain rules if used, so you can use @crossorigin annotations for more fine-grained cross-domain resource control.

1. Return new CorsFilter(global cross-domain)

In any configuration class, return a new CorsFIlter Bean and add the mapping path and the specific CORS configuration path.

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter(a) {
        //1. Add CORS configuration information
        CorsConfiguration config = new CorsConfiguration();
        // Which primitive fields are allowed
        config.addAllowedOrigin("*");
        // Whether to send cookies
        config.setAllowCredentials(true);
        // Which requests are allowed
        config.addAllowedMethod("*");
        // Which original request headers are allowed
        config.addAllowedHeader("*");
        // What header information is exposed
        config.addExposedHeader("*");
        //2. Add a mapping path
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/ * *",config);
        //3. Return a new CorsFilter
        return newCorsFilter(corsConfigurationSource); }}Copy the code

2. Rewrite WebMvcConfigurer(global Cross-domain)

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/ * *")
                // Whether to send cookies
                .allowCredentials(true)
                // Which primitive fields are allowed
                .allowedOrigins("*")
                .allowedMethods(new String[]{"GET"."POST"."PUT"."DELETE"})
                .allowedHeaders("*")
                .exposedHeaders("*"); }}Copy the code

3. Use annotations (local cross-domain)

Use the @crossorigin annotation on the controller:

@RestController
@CrossOrigin(origins = "*")
public class HelloController {
    @RequestMapping("/hello")
    public String hello(a) {
        return "hello world"; }}Copy the code

Use annotations on methods @crossorigin:

@RequestMapping("/hello")
    @CrossOrigin(origins = "*")
    public String hello(a) {
        return "hello world";
    }
Copy the code

4. Manually set response headers (local cross-domain)

Access-control-allow-origin authorizes the original field by adding a response header (access-Control-Allow-Origin) to the HttpServletResponse object, where Origin can also be set to “*” to permit all.

    @RequestMapping("/index")
    public String index(HttpServletResponse response) {
        response.addHeader("Access-Allow-Control-Origin"."*");
        return "index";
    }
Copy the code

References & acknowledgements

  • SpringBoot implements cross-domain access (CORS) with back-end separation
  • Cross-domain resource sharing (CORS