1、什么是跨域
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域
主要的表现形式:
| 跨域的原因 | 实例 |
|---|---|
| 域名不同 | www.jd.com与www.taobao.com |
| 域名相同,端口不同 | www.jd.com:8080 与www.jd.com:8081 |
| 二级域名不同 | item.jd.com与miaosha.jd.com |
反例:
域名和端口都相同,但是路径不同
2、为什么有跨域问题
跨域问题是浏览器对于ajax请求的一种安全限制,一个页面发起的ajax请求,只能是于当前页同域名的路径,这能有效的阻止跨站攻击。
因此,跨域是针对AJAX的一种限制,
3、解决方案
-
Jsonp
-
-
最早的解决方案,利用script标签可以跨域的原理实现
-
-
缺点
-
- 需要服务的限制
- 只能发送GET请求
-
-
-
nginx反向代理
-
-
利用nginx反向代理把跨域为不跨域,支持各种请求方式
-
-
缺点:
-
- 需要nginx进行额外配置,语义不清晰
-
-
-
CORS(跨域资源共享)
-
-
利用nginx反向代理把跨域为不跨域,支持各种请求方式
-
-
优势:
-
- 在服务端进行控制是否允许跨域,可自定义规则
- 支持各种请求
-
缺点:
-
- 会产生额外的请求
-
-
4、cors解决跨域问题
- 浏览器端都有浏览器自动完成,我们无需操心
- 服务端可以通过拦截器统一实现,不必每次都去进行跨域判定的编写
cors原理比较复杂,但是SpringMVC已经帮我们写好CORS的过滤器了 CorsFilter,
我们直接用就可以了,
方式一:
直接在controller,添加**@CrossOrigin**
方式二:
在网关配置:
@Configuration
public class GlobalCORSConfig {
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//1) 允许的域,不要写*,否则cookie就无法使用了
config.addAllowedOrigin("http://manage.xxx.com");
config.addAllowedOrigin("http://www.xxx.com");
//2) 是否发送Cookie信息
config.setAllowCredentials(true);
//3) 允许的请求方式
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
// 4)允许的头信息
config.addAllowedHeader("*");
// 5)有效期 单位秒
config.setMaxAge(3600L);
//2.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CORSFilter
return new CorsFilter(configSource);
}
优化:
1、把一些属性抽取application.yml
ly:
cors:
allowedOrigins:
- http://manage.xxx.com
allowedCredentials: true
allowedHeaders:
- "*"
allowedMethods:
- GET
- POST
- DELETE
- PUT
- OPTIONS
- HEAD
maxAge: 3600
filterPath: "/**"
2、定义一个配置类,加载这些属性
@Data
@ConfigurationProperties(prefix = "ly.cors")
public class CORSProperties {
private List<String> allowedOrigins;
private Boolean allowedCredentials;
private List<String> allowedMethods;
private List<String> allowedHeaders;
private Long maxAge;
private String filterPath;
3、读取配置
@Configuration
@EnableConfigurationProperties(CORSProperties.class)
public class GlobalCORSConfig {
@Bean
public CorsFilter corsFilter(CORSProperties prop) {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//1) 允许的域,不要写*,否则cookie就无法使用了
prop.getAllowedOrigins().forEach(config::addAllowedOrigin);
//2) 是否发送Cookie信息
config.setAllowCredentials(prop.getAllowCredentials());
//3) 允许的请求方式
prop.getAllowedMethods().forEach(config::addAllowedMethod);
// 4)允许的头信息
prop.getAllowedHeaders().forEach(config::addAllowedHeader);
// 5)配置有效期 单位秒
config.setMaxAge(prop.getMaxAge());
//2.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration(prop.getFilterPath(), config);
//3.返回新的CORSFilter.
return new CorsFilter(configSource);
}
}