@CrossOrigin
When building modern web applications based on a frontend-backend separation architecture, the browser's Same-Origin Policy is a critical mechanism for ensuring network security. However, this security feature often becomes an obstacle when interacting between the frontend and backend, causing AJAX, Fetch, or XMLHttpRequest requests to be intercepted due to cross-origin violations. As one of the core components of the Java Spring ecosystem, Spring MVC provides the @CrossOrigin annotation to elegantly address this issue. This article details the core functionality, configuration methods, and best practices for this annotation.
What is @CrossOrigin?
@CrossOrigin is a custom annotation provided by Spring Security (or Spring Web) primarily used to handle cross-origin issues in HTTP requests. When a browser initiates a request where the source address differs from the target server's, if the backend does not correctly respond with CORS (Cross-Origin Resource Sharing) header information, the frontend will be unable to retrieve data. By adding the @CrossOrigin annotation to a Controller method or class, Spring MVC automatically injects necessary HTTP header information into the response, informing the browser which sources are allowed to access that resource.
Core Configuration Parameters Explained
Although Spring Boot (based on Spring Security) may enable simple cross-origin support by default, we need to understand the key attributes of the @CrossOrigin annotation to exercise finer control over permissions and security:
- origin: Specifies a list of allowed request source addresses. It can be a specific domain name (e.g.,
https://example.com) or a wildcard (*) allowing all sources. Note: In production environments, unless the business truly requires fully open interfaces, it is not recommended to use*to avoid potential security risks. - allowCredentials: A boolean value indicating whether credentials such as Cookies and HTTP Authorization request headers are allowed to participate in cross-origin requests. The default is
false. If set totrue, specific origin whitelists must be configured, and wildcards cannot be used. - maxAge: An integer type specifying the cache duration unit (in seconds) for Preflight Requests. Browsers first send an OPTIONS request to ask if cross-origin access is allowed; this field tells the browser how long that answer can be cached to reduce unnecessary handshake counts.
Basic Usage Example
The most straightforward way to use @CrossOrigin is by adding it directly in a Spring MVC Controller. Below is an example handling a user login interface:
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
@RestController
@RequestMapping("/api/user")
public class UserController {
@GetMapping("/login")
// Allow requests from https://www.example.com and carry Cookie information
@CrossOrigin(origins = "https://www.example.com", allowCredentials = true)
public String login(@RequestParam String username,
@RequestParam String password) {
return "{\"code\":200,\"message\":\"Login successful\"}";
}
// Allow all sources but do not carry Cookies (commonly used for pure data exchange interfaces)
@GetMapping("/info")
@CrossOrigin(origins = "*", allowCredentials = false, maxAge = 3600)
public String getUserInfo() {
return "{\"id\":1,\"name\":\"Admin\"}";
}
// [Advanced] Use annotation arrays to support multiple interfaces configured simultaneously or custom class-level global configuration (requires coordination with Spring Security)
@CrossOrigin(origins = {"https://www.example.com", "https://app.example.com"},
allowCredentials = true, maxAge = 3600)
}
Global Effectiveness and Security Recommendations
In actual development, it is often desired for cross-origin configurations to apply to all interfaces or controllers under a specific package. Spring Boot versions 2.4+ introduced class-level support for the @CrossOrigin annotation (automatically injected via Spring Security), or more complex global strategies can be implemented through custom filters.
Important Security Notice:
- Avoid Wildcards with Cookies: If
allowCredentials = trueis set, absolutely prohibit using*in the origin. Because browsers will send credentials from all sources to servers on arbitrary domain names, this leads to severe privacy leakage risks (such as XSS attacks). In such cases, strictly limit the allowed list of domains. - Distinguish Interface Types: For APIs purely for data display, carrying Cookies is usually not required; however, for interfaces involving identity authentication or user session management,
allowCredentialsmust be enabled.
Comparison with Other CORS Configuration Methods
In addition to using annotations, you can also utilize Spring Boot's auto-configuration classes (such as CORSFilterConfiguration) or add global cross-origin support via WebMvcConfigurer:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // Matches all paths
.allowedOrigins("*")
.allowCredentials(false);
}
}
The advantage of this approach lies in centralized configuration, eliminating the need to repeatedly add annotations on every Controller method. However, regarding security considerations, global wildcards still require careful use. It is recommended to adopt a "Principle of Least Privilege" in production environments by opening only domain combinations necessary for business needs and combining them with Spring Security's authentication filters for dual protection.
Summary and Best Practices
@CrossOrigin is an excellent tool for solving frontend cross-origin issues, significantly reducing the environmental discrepancies encountered during frontend-backend integration testing. When applying this annotation, developers should always adhere to the following principles:
- Explicit Whitelists: Specify specific domain names as much as possible rather than using wildcards.
- Enable Credentials on Demand: Only set
allowCredentials = truefor interfaces involved in session management (login states). - Reasonably Cache Preflight Requests: For frequently accessed static resources or public APIs, appropriately increase the
maxAgevalue to improve performance.
By reasonably utilizing @CrossOrigin, we can achieve efficient collaborative development between frontend and backend while maintaining web application security.