Cross-Origin-Resource-Sharing (CORS) is a W3C specification which defines how a browser should be allowed using script to access different origin than the origin it has been served. With CORS, we can specify what kind of cross domain requests are authorized in a flexible way, instead of using some less secured and less powerful hacks like IFRAME or JSONP. In this tutorial, we’re gonna look at way to create a Spring Boot REST service with Spring CORS integration using @CrossOrigin
annotation.
Related Articles:
– Spring Boot – CORS Support using Java Config
– Spring Boot – CORS Support using XML Config
– AngularJs CrossSite HTTP Requests to SpringBoot RestAPIs
I. CORS Configuration using @CrossOrigin Annotation
1. On @RequestMapping-Annotated Method
@RestController public class WebController { @CrossOrigin(origins = { "http://localhost:8484", "http://localhost:9000" }, maxAge = 6000) @RequestMapping("customers") public ListgetCustomers() { // ... } @CrossOrigin(origins = { "http://localhost:9000" }, allowCredentials = "false") @RequestMapping("data") public List getData() { // ... } @RequestMapping("cart") public Cart getCart() { // ... } }
In the code above, CORS is not enabled for getCart()
method. getCustomers()
and getData()
have different CORS configuration.
– origins: specifies the URI that can be accessed by resource. “*” means that all origins are allowed. If undefined, all origins are allowed.
– allowCredentials: defines the value for Access-Control-Allow-Credentials response header. If value is true, response to the request can be exposed to the page. The credentials are cookies, authorization headers or TLS client certificates. The default value is true.
– maxAge: defines maximum age (in seconds) for cache to be alive for a pre-flight request. By default, its value is 1800 seconds.
We also have some attributes:
– methods: specifies methods (GET, POST,…) to allow when accessing the resource. If we don’t use this attribute, it takes the value of @RequestMapping
method by default. If we specify methods attribute value in @CrossOrigin
annotation, default method will be overridden.
– allowedHeaders: defines the values for Access-Control-Allow-Headers response header. We don’t need to list headers if it is one of Cache-Control, Content-Language, Expires, Last-Modified, or Pragma. By default all requested headers are allowed.
– exposedHeaders: values for Access-Control-Expose-Headers response header. Server uses it to tell the browser about its whitelist headers. By default, an empty exposed header list is used.
2. On Controller
@CrossOrigin(origins = { "http://localhost:9000" }, maxAge = 3000) @RestController public class WebController { @RequestMapping("customers") public ListgetCustomers() { // ... } @RequestMapping("data") public List getData() { // ... } }
If we use @CrossOrigin
annotation on the Controller, all CORS Configuration of methods inside will be enabled.
3. On Both
@CrossOrigin(origins = { "http://localhost:9000" }, maxAge = 3000) @RestController public class WebController { @CrossOrigin(origins = { "http://localhost:8484" }, maxAge = 6000) @RequestMapping("customers") public ListgetCustomers() { // ... } @RequestMapping("data") public List getData() { // ... } }
Spring will combine attributes from both to merge CORS configuration:
– /customers:
@CrossOrigin(origins = { "http://localhost:8484" , "http://localhost:9000" }, maxAge = 6000)
– /data:
@CrossOrigin(origins = { "http://localhost:9000" }, maxAge = 3000)
II. Practice
1. Technology
– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.4.RELEASE
– Spring Boot: 1.5.4.RELEASE
2. Project Overview
Dependency for Spring Boot Starter Web in pom.xml.
3. Step by step
3.1 Create Spring Boot project
Using Spring Tool Suite/Eclipse to create Project and add Dependencies to pom.xml file:
org.springframework.boot spring-boot-starter-web
3.2 Create Data Model Classes
package com.javasampleapproach.cors.model; public class Customer { private Long id; private String name; public Customer(Long id, String name) { this.id = id; this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
3.3 Create Service
package com.javasampleapproach.cors.service; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; import com.javasampleapproach.cors.model.Customer; @Service public class CustomerService { public ListgetCustomers() { List list = new ArrayList<>(); list.add(new Customer(1L, "Jack")); list.add(new Customer(2L, "Adam")); list.add(new Customer(3L, "Kim")); return list; } }
3.4 Create Controller
package com.javasampleapproach.cors.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.javasampleapproach.cors.model.Customer; import com.javasampleapproach.cors.service.CustomerService; @CrossOrigin(origins = { "http://localhost:9000" }, maxAge = 3000) @RestController public class WebController { @Autowired private CustomerService service; @CrossOrigin(origins = { "http://localhost:8484" }, maxAge = 6000) @RequestMapping("customers") public ListgetCustomers() { List list = service.getCustomers(); return list; } @RequestMapping("data") public List getData() { List list = service.getCustomers(); list.forEach(item -> item.setName(item.getName().toUpperCase())); return list; } }
3.5 Run & Check Result
– Config maven build:
clean install
– Run project with mode Spring Boot App and port 8080.
– Create Client Application (stored in folder webapps/Cors of Apache Tomcat):
$(document).ready(function() { $.ajax({ url: "http://localhost:8080/customers" }).then(function(data) { var items = []; $.each( data, function( key, val ) { items.push("Id: "+val.id +", Name: "+val.name+"
"); }); $('.result').append(items); }); });
Spring Boot - CORS
– Deploy client project on Tomcat with port 8484:
Send Request on Browser:
http://localhost:8484/Cors/index.html
Result:
Id: 1, Name: Jack Id: 2, Name: Adam Id: 3, Name: Kim
Clear Browser Cache, then modify data.js file by changing url to:
$.ajax({ url: "http://localhost:8080/data" })
Send Request on Browser:
http://localhost:8484/Cors/index.html
Result: Browser shows nothing.
– Deploy client project on Tomcat with port 9000:
Clear Browser Cache, then send Request on Browser:
http://localhost:9000/Cors/index.html
Result:
Id: 1, Name: JACK Id: 2, Name: ADAM Id: 3, Name: KIM
III. Source Code
– SpringBootCORS
– Cors