1)局部配置 CORS,在 controller 上使用
@CrossOrigin
注解。这种方式简单直接,适合对类进行跨域设置。
2)全局配置 CORS,可以通过实现 WebMvcConfigurer 接口并重写 addCorsMappings 方法,可以对整个应用程序进行统一的跨域配置。
3)还可以添加
CorsFilter
来处理跨域请求。(或者可以自定义 Filter,但是没必要,因为本身已经提供了 CorsFilter)
扩展 cors 策略配置参数说明
addCorsMappings 部分参数说明(CorsFilter 同理):
-
addMapping("/**"):允许所有路径的请求。
-
allowedOrigins("https://mianshiya.com"):允许来自 https://mianshiya.com 的请求。
-
allowedMethods("GET", "POST", "PUT", "DELETE"):允许的 HTTP 方法。
-
allowedHeaders("*"):允许的请求头。
-
allowCredentials(true): 是否允许发送 Cookie。
-
maxAge(3600):预检请求的缓存时间,单位为秒。
如果用了 addCorsMappings 可能有有坑!
假如我们配置了 addCorsMappings ,项目里还用了 Interceptor,此时就会发生问题!
例如部分接口需要 jwt 权限验证:
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JwtInterceptor()).addPathPatterns("/user/**").
excludePathPatterns("/login");
}
正常请求是没问题的,但是部分请求没带 token 的话,此时浏览器直接报跨域问题,好像 addCorsMappings 失效了一样。
主要原因是因为请求顺序导致的,请求会先进入拦截器,默认配置了 addCorsMappings 操作后,实际上会加了一个 CorsInterceptor,
但是这个拦截器的优先级在最后
。
所以,如果一个请求被前面的拦截器拦截后,直接返回,就不会经过 CorsInterceptor,这样一来返回的响应头上就不包含跨域的相关信息,因此浏览器就会继续报跨域错误!
此时有一种方法,就是在 JwtInterceptor 内直接放行预检请求,让它能访问到 CorsInterceptor 添加响应头。
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
return true;
}
还有一种更优雅的方式就是使用 CorsFilter
Filter 是过滤器,它是属于 servlet,而 Interceptor 是属于 Spring 的,因此 Filter 执行的优先级高于 Interceptor。
扩展:什么是跨域和同源策略
跨域请求
指的是浏览器从一个不同于当前网页所在的域名向另一个域名发起的请求。比如从 https://mianshiya.com 向 https://api.mianshiya.com 发起请求。
同源策略
它是浏览器的安全策略,只允许同源(
协议、域名、端口都相同
)的请求,跨域请求默认会被阻止。