Spring Boot CORS @CrossOrigin Example

Cross-Origin Resource Sharing (CORS) is a security concept that allows restricting the resources implemented in web browsers. It prevents the JavaScript code producing or consuming the requests against different origin.
For security reasons, browsers don’t allow you to make AJAX requests to resources residing outside of the current origin. CORS specification (https://www.w3.org/TR/cors/) provides a way to specify which cross-origin requests are permitted.
SpringMVC provides support for enabling CORS for REST API endpoints so that the API consumers, such as web clients and mobile devices, can make calls to REST APIs.
For example, your web application is running on 8080 port and by using JavaScript you are trying to consuming RESTful web services from 9090 port. Under such situations, you will face the Cross-Origin Resource Sharing security issue on your web browsers.
Two requirements are needed to handle this issue −
  • RESTful web services should support Cross-Origin Resource Sharing.
  • RESTful web service application should allow accessing the API(s) from the 8080 port.

1. Class-Level and Method-Level CORS Configuration

You can enable CORS at the controller level or at the method level using the @CrossOrigin annotation.

1.1 Spring Boot CORS – Method level with @CrossOrigin

Let's see how we can enable CORS support on a specific request handling method.
@RestController
@RequestMapping("/api/v1")
public class TodoController {

    @Autowired
    private TodoRepository todoRepository;

    @CrossOrigin
    @GetMapping("/users/{username}/todos")
    public List < Todo > getAllTodos(@PathVariable String username) {
        return todoRepository.findByUsername(username);
    }
}
Here, the CORS support enables only the getAllTodos() method using the default configuration.
  • All headers and origins are permitted
  • Credentials are allowed
  • Maximum age is set to 30 minutes
  • The list of HTTP methods is set to the methods on the @RequestMethod annotation
We can customize these properties by providing options on the @CrossOrigin annotation:
@RestController
@RequestMapping("/api/v1")
public class TodoController {

    @Autowired
    private TodoRepository todoRepository;

    @CrossOrigin(origins = {
            "http://domain1.com",
            "http://domain2.com"
        },
        allowedHeaders = "X-AUTH-TOKEN",
        allowCredentials = "false",
        maxAge = 15 * 60,
        methods = {
            RequestMethod.GET,
            RequestMethod.POST
        })

    @GetMapping("/users/{username}/todos")
    public List < Todo > getAllTodos(@PathVariable String username) {
        return todoRepository.findByUsername(username);
    }
}

1.2 Spring Boot CORS – Class level with @CrossOrigin

Let's apply the @CrossOrigin annotation at the controller class level. 
When applied at the class level, the same @CrossOrigin configuration is applied to all the @RequestMapping methods. If the @CrossOrigin annotation is specified at both the class level and the method level, Spring will derive the CORS configuration by combining attributes from both annotations.
@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api/v1")
public class TodoController {

    @Autowired
    private TodoRepository todoRepository;

    @GetMapping("/users/{username}/todos")
    public List < Todo > getAllTodos(@PathVariable String username) {
        return todoRepository.findByUsername(username);
    }

    @CrossOrigin
    @GetMapping("/users/{username}/todos/{id}")
    public Todo getTodo(@PathVariable String username, @PathVariable long id) {
        return todoRepository.findById(id).get();
    }

    @DeleteMapping("/users/{username}/todos/{id}")
    public ResponseEntity < Void > deleteTodo(@PathVariable String username, @PathVariable long id) {
        todoRepository.deleteById(id);
        return ResponseEntity.noContent().build();
    }

    @PutMapping("/users/{username}/todos/{id}")
    public ResponseEntity < Todo > updateTodo(@PathVariable String username, @PathVariable long id,
        @RequestBody Todo todo) {
        Todo todoUpdated = todoRepository.save(todo);
        return new ResponseEntity < Todo > (todoUpdated, HttpStatus.OK);
    }

    @PostMapping("/users/{username}/todos")
    public ResponseEntity < Void > createTodo(@PathVariable String username, @RequestBody Todo todo) {
        todo.setUsername(username);
        Todo createdTodo = todoRepository.save(todo);
        URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(createdTodo.getId())
            .toUri();

        return ResponseEntity.created(uri).build();
    }
}

2. Spring Boot CORS - Global CORS Configuration

In addition to specifying CORS configuration at the class and method levels, we can configure it globally by implementing the WebMvcConfigurer.addCorsMappings() method.
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins("http://localhost:4200")
            .allowedMethods("*")
            .allowedHeaders("*")
            .allowCredentials(false)
            .maxAge(3600);
    }
}
This configuration enables the CORS for URL pattern /api/** from the origin http://localhost:4200 only. You can specify allowedOrigins("*") to allow requests from any origin.

Comments