This is the third day of my participation in the November Gwen Challenge. Check out the details: the last Gwen Challenge 2021.

Cross-origin Resource Sharing is a new feature in HTML 5 that allows us to determine whether resources are allowed to be accessed across domains while developing back-end systems. The so-called cross-domain refers to different domain names or ports or protocols. For example, when accessing mrbird.cc:8080 website resources from mrbrid.cc website, there will be cross-domain problems. Spring has cross-domain support since version 4.2, right out of the box. This paper introduces how to solve cross-domain problems in Spring Boot development, mainly divided into annotation driver and interface programming.

Simulation of cross-domain

To solve a cross-domain problem, we must first simulate a cross-domain scenario. Create a New Spring Boot project and introduce the following dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Copy the code

Create controller package in com.example.demo and create TestController:

@Controller
public class TestController {

    @RequestMapping("index")
    public String index (a) {
        return "index";
    }

    @RequestMapping("hello")
    @ResponseBody
    public String hello(a){
        return "hello"; }}Copy the code

Then go to Resources /templates and create index.html:

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cross-domain test</title>
    <script src="http://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<div id="hello"></div>
</body>
<script>
    $(function () {
        $.get("http://test.mrbird.cc:8080/hello".function (data) {$("#hello").text(data); })})</script>
</html>
Copy the code

Start the project and visit http://localhost:8080/. The page does not display Hello successfully, and F12 looks at the browser console and sees an error:

Annotation driven

Spring 4.2 provides the @Crossorigin annotation, which can be annotated on a method or class and contains the following attributes:

attribute meaning
value Specify the collection of supported domains,*Indicates that all domains are supported. The default value is*. These values correspond to those in the HTTP request headerAccess-Control-Allow-Origin
origins With the value
allowedHeaders Headers are allowed in the request header, and are supported by default
exposedHeaders The allowed header in the response header, which is null by default
methods Methods to support requests, such asGET.POST.PUTAnd so on, the default is the same as marked on the method in Controller.
allowCredentials Whether cookies are allowed to be sent with the request must be specified when used
maxAge The validity period of the pre-requested results, 30 minutes by default

Let’s modify the Hello method in TestController:

@RequestMapping("hello")
@ResponseBody
@CrossOrigin(value = "*")
public String hello(a) {
    return "hello";
}
Copy the code

Indicates that all domains are allowed to support, restart the project.

Interface programming

In addition to using @crossorigin annotations, we can use interface programming for unified configuration.

Create the config package in the com.example.demo path, and then create WebConfigurer, implement WebMvcConfigurer, and override the addCorsMappings default implementation:

@Configuration
public class WebConfigurer implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/ * *")
                .allowedOrigins("*")
                .allowedMethods("GET"); }}Copy the code

The above configuration allows all requests to support cross-domain access and does not limit the domain, but supports the GET method. Comment out the @crossorigin annotation on the Hello method, restart the project, and visit http://localhost:8080/ again. The result is also OK.

Filter implementation

The official documentation also provides a filter-based implementation:

@Bean
public FilterRegistrationBean corsFilter(a) {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    source.registerCorsConfiguration("/ * *", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}
Copy the code

Physical cross domain

If related functions of the Actuator are integrated in the project, and the interfaces exposed by the Actuator are cross-domain, you only need to add the following configuration in the configuration file:

ENDPOINTS CORS CONFIGURATION (CorsEndpointProperties)

management.endpoints.web.cors.allow-credentials= # Whether credentials are supported. When not set, credentials are not supported.
management.endpoints.web.cors.allowed-headers= # Comma-separated list of headers to allow in a request. '*' allows all headers.
management.endpoints.web.cors.allowed-methods= # Comma-separated list of methods to allow. '*' allows all methods. When not set, defaults to GET.
management.endpoints.web.cors.allowed-origins= # Comma-separated list of origins to allow. '*' allows all origins. When not set, CORS support is disabled.
management.endpoints.web.cors.exposed-headers= # Comma-separated list of headers to include in a response.
management.endpoints.web.cors.max-age=1800s # How long the response from a pre-flight request can be cached by clients. If a duration suffix is not specified, seconds will be used.
Copy the code