理解并解决CORS跨域问题

175 阅读2分钟

跨源资源共享(CORS)是一种机制,允许许多安全的跨源请求,比如Ajax。在本文中,我们将首先介绍CORS的基本原理,然后会详细讨论在Spring框架中配置CORS的几种方法。

1. CORS的基本原理

当你试图从一个不同的源(域名、协议或端口)执行XMLHttpRequest或Fetch时,浏览器会实现同源策略来阻止这种行为。CORS就是一种让服务器告诉浏览器应该放宽同源策略的机制。

在CORS机制中,浏览器会在跨源HTTP请求上发送额外的 "CORS headers",其中一些是在请求中,一些是在响应中。这些头信息告诉浏览器应该如何处理跨源请求和响应。

2. 在Spring框架中配置CORS

在Spring框架中,有多种方式可以配置支持跨域请求。以下是几种常见的方法:

2.1 在过滤器中添加CORS头信息

你可以创建一个自定义的Servlet过滤器来处理跨域请求。这个过滤器会检查请求的源(即 ORIGIN 头),并根据这个源是否在白名单中,决定是否在响应头添加CORS相关的信息。

在下面的示例中,doFilter 方法会检查 ORIGIN 是否在白名单中,如果在的话,就向响应头添加CORS相关的头信息,包括 Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Max-AgeAccess-Control-Allow-HeadersAccess-Control-Allow-Credentials

response.setHeader("Access-Control-Allow-Origin", safeOrigin);
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,content-type,token");
response.setHeader("Access-Control-Allow-Credentials", "true");

2.2 使用@CrossOrigin注解

在Spring MVC的控制器或处理程序方法上使用@CrossOrigin注解,可以为特定的HTTP请求处理程序启用CORS。例如:

@RestController
public class MyController {

    @CrossOrigin(origins = "http://example.com")
    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }
}

在这个例子中,只有来自http://example.com的请求才会被接受。

2.3 全局CORS配置

你可以在Spring MVC中使用Java配置来定义全局CORS配置。这可以通过重写addCorsMappings(CorsRegistry registry)方法来完成。例如:

@Configuration
public class MyConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOrigins("http://example.com")
            .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
            .allowCredentials(true)
            .maxAge(3600);
    }
}

在这个例子中,所有的URL路径都允许来自http://example.com的跨域请求。

2.4 使用Spring Boot的CorsFilter

如果你正在使用Spring Boot,你可以直接在配置文件中定义CORS映射,然后通过CorsFilter来应用这些映射。例如:

@Configuration
public class MyConfiguration {

    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://example.com");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
}

在这个例子中,所有的URL路径都允许来自http://example.com的跨域请求。