1. Introduction to cross-domain issues
In web development, the Same-Origin Policy of a browser is an important security mechanism that limits how documents or scripts loaded in one source interact with resources from another source. The so-called homologous origin refers to the same protocol, domain name and port number. When the current application tries to request a backend API with a different origin from its own, it will encounter cross-domain problems.
For example, whenFront-end application attempts to access
/api
When the backend service is used, the browser will block such requests and report an error in the console:
Access to XMLHttpRequest at '/api' from origin ''
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Cross-Origin Resource Sharing (CORS) is a standard mechanism that allows servers to declare which sources can access their resources. In SpringBoot applications, there are many ways to solve cross-domain problems. The following is a detailed introduction to 6 common solutions.
2. Solution 1: Method level control based on @CrossOrigin annotation
This is the easiest and straightforward way to add it on the Controller class or a specific method@CrossOrigin
Annotation to allow cross-domain requests.
Implementation method
// Allow cross-domain at method level@RestController @RequestMapping("/api") public class UserController { @CrossOrigin(origins = "") @GetMapping("/users") public List<User> getUsers() { // Method implementation return (); } @GetMapping("/roles") public List<Role> getRoles() { // This method does not allow cross-domain return (); } } // Allow cross-domain at class level@CrossOrigin(origins = {"", "http://localhost:3000"}) @RestController @RequestMapping("/api/products") public class ProductController { @GetMapping public List<Product> getAllProducts() { // Method implementation return (); } @GetMapping("/{id}") public Product getProduct(@PathVariable Long id) { // Method implementation return (id); } }
advantage
- Achieve simple and intuitive
- Can be precisely controlled to the method level
- Different CORS rules can be set for different APIs
shortcoming
- The code is repeated, and you need to add annotations in multiple places
- Maintenance cost is high. When the CORS policy changes, multiple codes need to be modified.
- Not suitable for unified management of CORS policies in large projects
3. Solution 2: Global CORS configuration (WebMvcConfigurer)
By implementingWebMvcConfigurer
Interface and rewriteaddCorsMappings
Method, you can configure CORS rules globally.
Implementation method
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { ("/api/**") .allowedOrigins("", "http://localhost:3000") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); // No pre-check is required within 1 hour (send OPTIONS request) } }
advantage
- It can facilitate centralized management of CORS configuration for all APIs
- Flexible configuration, different rules can be set for different URL patterns
- Concise code and easy to maintain
shortcoming
- In some scenarios, it may be necessary to use it in conjunction with other security configurations
4. Solution 3: Use CorsFilter
By definitionCorsFilter
As a Bean, cross-domain requests can be processed at the filter level, in this wayWebMvcConfigurer
higher priority.
Implementation method
@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); // Allowed sources (""); ("http://localhost:3000"); // Allowed HTTP methods ("*"); // Allowed header information ("*"); // Allow authentication information (cookies, etc.) (true); // The validity period of the pre-flight request is in seconds (3600L); // Apply these configurations to all URLs ("/**", config); return new CorsFilter(source); } }
advantage
- Processing at the filter level can intercept all requests
- Priority is higher than plan two
- Can be used in combination with other filters
- Suitable for adding CORS support without modifying the existing controller
shortcoming
- Unable to precisely control at the method level
- May not be flexible enough for complex rules
5. Solution 4: CORS configuration in Spring Security
If the project uses Spring Security, CORS needs to be allowed in the Security configuration, otherwise Security may intercept cross-domain requests.
Implementation method
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .cors(()) // Use the default configuration of CorsConfigurationSource .csrf().disable() .authorizeHttpRequests(authorize -> authorize .requestMatchers("/api/**").authenticated() .anyRequest().permitAll() ) .httpBasic(()); return (); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); (("", "http://localhost:3000")); (("GET", "POST", "PUT", "DELETE", "OPTIONS")); (("Authorization", "Content-Type")); (true); (3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); ("/**", configuration); return source; } }
advantage
- Seamless integration with Spring Security
- Can be configured in combination with authentication and authorization rules
- Suitable for REST APIs that require security control
shortcoming
- Depend on Spring Security
- It can be a bit complicated for simple applications that do not require security control
6. Solution 5: Solve cross-domain at the gateway level (Spring Cloud Gateway)
In the microservice architecture, cross-domain issues can be handled uniformly at the API gateway layer, so that back-end microservices do not need to configure CORS on their own.
Implementation method
// Spring Cloud Gateway configuration@Configuration public class GatewayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return () .route("user_service_route", r -> ("/api/users/**") .uri("lb://user-service")) .route("product_service_route", r -> ("/api/products/**") .uri("lb://product-service")) .build(); } @Bean public WebFilter corsFilter() { return (ServerWebExchange ctx, WebFilterChain chain) -> { ServerHttpRequest request = (); if ((request)) { ServerHttpResponse response = (); HttpHeaders headers = (); ("Access-Control-Allow-Origin", "*"); ("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); ("Access-Control-Allow-Headers", "Authorization, Content-Type"); ("Access-Control-Allow-Credentials", "true"); ("Access-Control-Max-Age", "3600"); if (() == ) { (); return (); } } return (ctx); }; } }
advantage
- Centrally handle cross-domain issues of all microservices
- Backend services do not need to care about cross-domain configuration
- Easy to manage and maintain uniformly
- Suitable for microservice architecture
shortcoming
- Relying on Spring Cloud Gateway
- Relatively complex configuration
- For monomer applications it may be too heavy
Scenario 6: Use a proxy server
Configure the front-end development server agent(Development Environment)Or use Nginx(Production Environment)Reverse proxy servers can indirectly solve cross-domain problems. This approach actually bypasses the browser's homologous policy, rather than directly solving CORS on the backend.
Front-end development server proxy configuration (taking Vue CLI as an example)
// = { devServer: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, pathRewrite: { '^/api': '/api' } } } } }
Nginx reverse proxy configuration
server { listen 80; server_name ; location / { root /usr/share/nginx/html; index ; try_files $uri $uri/ /; } location /api/ { proxy_pass :8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
advantage
- Completely bypass the browser's homologous policy restrictions
- No CORS configuration is required in the backend
shortcoming
- Requires additional proxy configuration
- Increases system complexity
- Additional network latency may be introduced
8. Comparison of plans and selection suggestions
plan | Difficulty to achieve | flexibility | Maintenance cost | Applicable scenarios |
---|---|---|---|---|
@CrossOrigin annotation | Low | high | high | Small projects, specific APIs need to cross domains |
WebMvcConfigurer | middle | middle | Low | Most Spring Boot apps |
CorsFilter | middle | middle | Low | Needs high priority CORS processing |
Spring Security | high | high | middle | Applications with security needs |
Gateway level solution | high | high | Low | Microservice architecture |
Proxy server | middle | high | middle | Production environment, strict safety requirements |
9. Best practices and precautions
1. Safety considerations
- Don't set it blindly
Access-Control-Allow-Origin: *
, the allowed sources should be specified explicitly - Handle requests with credentials (such as cookies) with caution, ensuring that only trusted sources are allowed
- For sensitive operations, consider using CSRF tokens for protection
2. Performance optimization
- Reasonable setting
Access-Control-Max-Age
To reduce preflight requests - Avoid parsing and building CORS headers in every request
- Handling CORS at the gateway layer can reduce the burden on backend services
3. Development and debugging
- CORS restrictions can be appropriately relaxed in the development environment, but must be tightened in the production environment
- Debugging CORS issues using the Network panel of browser developer tools
10. Summary
Cross-domain requests are an inevitable problem in front-end and back-end separation, and Spring Boot provides a variety of solutions. From simple@CrossOrigin
Annotating complex gateway configurations, we can choose the appropriate solution based on project size and needs. In actual development, it is recommended to consider security, flexibility and maintenance costs comprehensively and select the CORS solution that is most suitable for the project.
For most Spring Boot applications, it is recommended to use the global CORS configuration (WebMvcConfigurer) solution, which provides good balance; for microservice architecture, it is recommended to handle CORS problems uniformly at the gateway layer to reduce the configuration burden of back-end services.
Regardless of the option you choose,All should follow the "minimum permission principle", only necessary sources are allowed to access necessary resources to ensure the security of the system.
The above are the detailed contents of 6 SpringBoot methods to solve cross-domain requests. For more information about SpringBoot solving cross-domain requests, please follow my other related articles!