Developer Playground

CORS (Cross-Origin Resource Sharing) & SOP (Same-Origin Policy)

Updated: April 30, 2025

What is CORS?

CORS stands for Cross-Origin Resource Sharing. The term "Cross-Origin Resource Sharing" is self-explanatory when broken down:

  • Origin refers to a combination of Protocol + Host + Port
  • For example, http://localhost:8080 is one Origin
  • Cross-Origin simply means when Origins are different
Path of standard latency Path of added latency JavaScript makes a cross-domain XHR call Is it a GET or HEAD? Is it a POST? Is the content- type standard? Are there custom HTTP headers? Make OPTIONS call to server with all custom details Did server respond with appropriate Access-Control-* headers? Make actual XHR ERROR Yes No Yes No Yes No No Yes Yes No

What does "Different Origin" mean?

If any of Protocol, Host, or Port are different, it's considered Cross-Origin:

  • http://localhost:8080 and http://localhost:9090 are Cross-Origin (different port)
  • http://example.com and https://example.com are Cross-Origin (different protocol)
  • https://example.com and https://www.example.com are Cross-Origin (different host)

What is Resource Sharing?

Resource sharing in the context of web applications refers to how applications access and exchange data:

  • A web application can serve its own resources to visitors
  • It can also request resources from other servers
  • Or make requests to create, delete, or modify resources on other servers
  • When making requests to other servers, this means making requests to Cross-Origin
  • Therefore, this concept refers to sharing resources between different Origins
CORS & SOP Overview Origin A https://example.com Protocol: HTTPS Host: example.com Port: 443 (default) Origin B http://api.example.com:8080 Protocol: HTTP Host: api.example.com Port: 8080 CORS Cross-Origin Request Different Protocol, Host, or Port

What is SOP?

SOP stands for Same-Origin Policy, a critical security concept in web application security:

  • When Protocol, Host, and Port are all identical, it's called Same-Origin
  • SOP is a security feature implemented by web browsers
  • It restricts how a document or script loaded from one origin can interact with resources from another origin
  • This policy helps isolate potentially malicious documents and mitigate attack vectors

Why Limit Cross-Origin Requests?

The Same-Origin Policy was established primarily to address security concerns:

  • It helps prevent CSRF (Cross-Site Request Forgery) attacks
  • For example, if a malicious site (https://naber.com) creates an iframe displaying a legitimate site (https://naver.com), a user might not notice the difference and log in
  • The malicious site could then use the user's credentials to perform unintended actions on the legitimate site
  • SOP prevents scripts from one origin from accessing or modifying data from another origin
  • CORS provides a way to safely relax this restriction when necessary

What is a Simple Request?

Simple Requests are a category of requests that are somewhat exempt from the strict CORS policy:

  • Requests that meet all of the following conditions are considered Simple Requests:
  • HTTP Method: Only GET, HEAD, or POST
  • Content-Type: Only text/plain, application/x-www-form-urlencoded, or multipart/form-data
  • No custom headers are included in the request

Simple requests don't trigger a preflight request, simplifying the cross-origin process.

What is a Preflight Request?

Preflight requests are an important security mechanism in the CORS process:

  • A preflight request is made for all requests that are not Simple Requests
  • It's an OPTIONS HTTP request sent before the actual request
  • It verifies that the CORS protocol is understood and that the server permits the actual request
  • The preflight request includes headers like:
  • Access-Control-Request-Method: Specifies the HTTP method of the actual request
  • Access-Control-Request-Headers: Lists any custom headers that will be used

The server must respond with appropriate Access-Control-* headers to allow the actual request to proceed.

How to implement in spring boot?

Preflight requests are an important security mechanism in the CORS process:

  • A preflight request is made for all requests that are not Simple Requests
  • It's an OPTIONS HTTP request sent before the actual request
  • It verifies that the CORS protocol is understood and that the server permits the actual request
  • The preflight request includes headers like:
  • Access-Control-Request-Method: Specifies the HTTP method of the actual request
  • Access-Control-Request-Headers: Lists any custom headers that will be used

The server must respond with appropriate Access-Control-* headers to allow the actual request to proceed.

Spring Boot 3 CORS Implementation Methods

There are several ways to implement CORS in Spring Boot 3. The main methods are as follows:

1. Using @CrossOrigin Annotation

This method configures CORS at the controller class or method level.

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(origins = "http://example.com",
             allowedHeaders = "*",
             methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT},
             maxAge = 3600)
public class MyController {

    @GetMapping("/api/data")
    public ResponseEntity<?> getData() {
        // Method implementation
        return ResponseEntity.ok().body(data);
    }

    // You can also apply different CORS settings to specific methods
    @CrossOrigin(origins = "http://another-domain.com")
    @PostMapping("/api/submit")
    public ResponseEntity<?> submitData(@RequestBody DataDTO data) {
        // Method implementation
        return ResponseEntity.ok().build();
    }
}

2. Global CORS Configuration with WebMvcConfigurer

This method applies CORS settings to the entire application.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")  // Apply to all paths
                .allowedOrigins("http://example.com", "https://example.org")  // Origins to allow
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")  // HTTP methods to allow
                .allowedHeaders("*")  // Allow all headers
                .allowCredentials(true)  // Allow credentials
                .maxAge(3600);  // Preflight request cache time (seconds)
    }
}

3. Configuration Using CorsFilter

This method configures CORS at the filter level. It's useful when using Spring Security.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();

        // Configure allowed origins
        config.addAllowedOrigin("http://example.com");
        config.addAllowedOrigin("https://example.org");

        // Set preflight request cache time
        config.setMaxAge(3600L);

        // Allow credentials (cookies, authentication headers, etc.)
        config.setAllowCredentials(true);

        // Configure allowed HTTP methods
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("OPTIONS");

        // Allow all headers
        config.addAllowedHeader("*");

        // Configure exposed response headers
        config.addExposedHeader("Authorization");

        // Apply this configuration to all paths
        source.registerCorsConfiguration("/**", config);

        return new CorsFilter(source);
    }
}

4. CORS Configuration with Spring Security

When using Spring Security, you need to add CORS configuration to the SecurityFilterChain.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // Enable CORS configuration
            .cors().and()
            .csrf().disable()  // Disable CSRF (common for API servers)
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            );

        return http.build();
    }

    // Define CorsConfigurationSource bean
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        configuration.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

Handling Preflight Requests

If you want to explicitly handle preflight requests (OPTIONS method), you can add the following to your controller:

@RestController
public class CorsController {

    @RequestMapping(value = "/**", method = RequestMethod.OPTIONS)
    public ResponseEntity<?> handleOptionsRequest() {
        return ResponseEntity
            .ok()
            .build();
    }
}
CORS Preflight Process Browser Server 1. Preflight Request (OPTIONS) Access-Control-Request-Method: PUT Access-Control-Request-Headers: Content-Type 2. Preflight Response Access-Control-Allow-Origin: https://example.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: Content-Type 3. Actual Request (Only if preflight successful) Success

Conclusion

CORS is a crucial security mechanism that enables controlled cross-origin resource sharing while protecting users from potential attacks. Understanding how CORS works with the Same-Origin Policy is essential for modern web application development.

By properly implementing CORS, you can build secure web applications that safely interact with resources from different origins while maintaining security best practices.


Advertisement