问题的出现:两个域名不同(端口不同)之间,发送ajax异步请求,浏览器认为这是危险的,从而有了跨域问题
目前比较常用的跨域解决方案有3种:
- Jsonp
最早的解决方案,利用script标签可以跨域的原理实现。
限制:
- 需要服务的支持
- 只能发起GET请求
- nginx反向代理
思路是:利用nginx反向代理把跨域为不跨域,支持各种请求方式
缺点:需要在nginx进行额外配置,语义不清晰 - CORS
规范化的跨域请求解决方案,安全可靠。
优势:
- 在服务端进行控制是否允许跨域,可自定义规则
- 支持各种请求方式
缺点:
- 会产生额外的请求
cors解决方法: —— 浏览器将ajax请求分为两类
- 简单请求:
head、get、post
这时浏览器请求头中会携带origin字段,指出请求属于哪个域(协议+域名+端口)
响应头里含有以下两个信息,便能实现跨域请求
Assess-Controller-Allow-Origin:可以接受的域
Assess-Controller-Allow-Credentials:是否允许写带cookie信息
- 特殊请求
如put请求
这时浏览器会执行预检,在简单请求的请求头基础上再增加两个字段分别是
Assess-Controller-Request-Methods:请求方法
Assess-Controller-Request-Headers:额外的请求头信息
若响应头有如下信息,便能执行跨域请求
Assess-Controller-Allow-Origin 允许的域
Assess-Controller-Allow-Credentials 是否发送cookie
Assess-Controller-Allow-Methods:允许的方法
Assess-Controller-Allow-Headers:允许携带的头信息
Assess-Controller-Max-Age:本次许可时间
cors跨域过滤器代码如下:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 跨域过滤器
*/
@Configuration // 启动容器加载bean
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter(){
// 1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
// 1.1 允许通过的域 ,不要写*,否则cookie无法使用
config.addAllowedOrigin("http://manage.111.com");
config.addAllowedOrigin("http://api.l111.com");
config.addAllowedOrigin("http://www.111.com");
config.addAllowedOrigin("http://image.111.com");
// 1.2是否发送cookie信息
config.setAllowCredentials(true);
// 1.3 允许通过的请求方式
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
// 1.4 允许通过的请求头信息
config.addAllowedHeader("*");
// 1.5 有效时间
config.setMaxAge(360000L);
// 2.添加映射路径,拦截一切请求
UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
configurationSource.registerCorsConfiguration("/**",config);
// 3.返回新的资源CorsFilter
return new CorsFilter(configurationSource);
}
}
方便维护过滤器配置代码:(推荐使用)
/**
* 网关
*/
//@SpringBootApplication
//@EnableDiscoveryClient
@SpringCloudApplication
@EnableZuulProxy // 声明是一个网关启动类
@EnableConfigurationProperties(CORSProperties.class)
public class lyGateway {
public static void main(String[] args) {
SpringApplication.run(lyGateway.class,args);
}
}
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
/**
* 跨域资源实体类
*/
@Data
@ConfigurationProperties(prefix = "ly.cors")
public class CORSProperties {
private List<String> allowedOrigins; //允许通过的域
private Boolean allowedCredentials; // 是否发送cookie信息
private List<String> allowedMethods; // 允许通过的请求方式
private List<String> allowedHeaders; // 允许通过的请求头信息
private Long maxAge; // 有效时间
private String filterPath; // 添加映射路径,拦截一切请求
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 跨域过滤器
*/
@Configuration // 声明是一个配置,启动容器加载bean
public class GlobalCorsConfig {
@Autowired
private CORSProperties prop;
/**
* @bean 自动执行当前方法,而且会把方法放入IOC容器中
* 如果当前方法有参数,会自动去IOC容器中寻找同类型的对象,作为参数使用
* @return
*/
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//1) 允许的域,不要写*,否则cookie就无法使用了
prop.getAllowedOrigins().forEach(config::addAllowedOrigin);
//2) 是否发送Cookie信息
config.setAllowCredentials(prop.getAllowedCredentials());
//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);
}
}
# 跨域过滤器
ly:
cors:
allowedOrigins:
- http://manage.111.com
- http://api.111.com
- http://www.111.com
- http://image.111.com
allowedCredentials: true
allowedHeaders:
- "*"
allowedMethods:
- GET
- POST
- DELETE
- PUT
- OPTIONS
- HEAD
maxAge: 360000
filterPath: "/**"