Understanding Cross-Origin Resource Sharing (CORS)
Cross-origin requests occur when a web application at one origin attempts to communicate with a server at a different origin. An origin is defined by the combination of protocol (http/https), domain name, and port number. The Same-Origin Policy, a fundamental security mechanism in web browsers, restricts such interactions to prevent malicious activities.
| Current Page URL | Target Page URL | Cross-Origin? | Reason |
|---|---|---|---|
| http://www.example.com/ | http://www.example.com/page.html | No | Same protocol, domain, and port |
| http://www.example.com/ | https://www.example.com/page.html | Yes | Protocol differs (http vs https) |
| http://www.example.com/ | http://api.example.com/ | Yes | Subdomain differs (www vs api) |
| http://www.example.com:8080/ | http://www.example.com:3000/ | Yes | Port differs (8080 vs 3000) |
Backend Configuration with Spring Boot
Global CORS Configuration
Implement a configuration class to global handle CORS for all endpoints:
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 CorsGlobalConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/resources/**")
.allowedOriginPatterns("http://localhost:3000", "https://yourdomain.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
Controller-Level CORS
Apply CORS annotations directly to controllers or specific methods:
@RestController
@CrossOrigin(origins = {"http://localhost:3000"}, maxAge = 3600)
public class DataController {
@GetMapping("/data")
public ResponseEntity<List<DataItem>> getData() {
// Implementation
}
}
Frontend Configuration with Vue.js
Vue Configuration File Setup
Configure proxy settings in vue.config.js to handle CORS during development:
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
devServer: {
port: 3000,
proxy: {
'/service': {
target: 'http://localhost:8080',
changeOrigin: true,
secure: false,
pathRewrite: {
'^/service': '/api'
}
}
}
},
productionSourceMap: false
}
Proxy Configuraton Explanation
The proxy configuration works as follows:
- Requests starting with '/service' are intercepted
- The target server receives the request at http://localhost:8080
- The pathRewrite rule replaces '/service' with '/api'
- For example: http://localhost:3000/service/users → http://localhost:8080/api/users
Axios Request Example
import axios from 'axios';
const apiClient = axios.create({
baseURL: '/service',
timeout: 5000
});
export default {
fetchUserData() {
return apiClient.get('/users');
}
}