1、为什么会出现跨域
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。
同源策略是浏览器安全的基石。若地址里面的协议、域名和端口号均相同则属于同源。
http的请求url一般格式:协议+域名(子域名+主域名)+端口号+资源地址 所以只要协议,子域名,主域名,端口号这四项组成部分中有一项不同,就可以认为是不同的域,不同的域之间互相访问资源,就被称之为跨域。
2、解决跨域分析
CORS全称为Cross Origin Resource Sharing(跨域资源共享),
每一个页面需要返回一个名为 Access-Control-Allow-Origin的http头来允许外域的站点访问,你可以仅仅暴露有限的资源和有限的外域站点访问。
我们可以理解为:如果一个请求需要允许跨域访问,则需要在http头中设置。
我们先来了解几个和cors相关的属性
Access-Control-Allow-Origin: www.toutiao.com
Access-Control-Allow-Methods: GET,POST,PUT,DELETE
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1800
它们的含义分别是
Access-Control-Allow-Origin:
Access-Control-Allow-Methods: 真实请求允许的方法
Access-Control-Allow-Headers: 服务器允许使用的字段
Access-Control-Allow-Credentials: 是否允许用户发送、处理 cookie Access-Control-Max-Age: 预检请求的有效期,单位为秒。有效期内,不会重复发送预检请求
故此我们可以通知配置以上属性值来解决跨域的问题。
3、解决方案
方案一:使用@CrossOrigin注解
// 所有域名可以访问
@CrossOrigin
// 指定域名访问
@CrossOrigin("www.toutiao.com")
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
return "ok";
}
}
方案二:CORS全局配置
@Configuration
public class CorsConfiguration implements WebMvcConfigurer {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").
// 允许跨域的域名,可以用*表示允许任何域名使用
allowedOrigins("https://www.toutiao.com").
// 允许任何方法(post、get等)(可以按需指定)
allowedMethods("*").
// 允许任何请求头(可以按需指定)
allowedHeaders("*").
// 带上cookie信息
allowCredentials(true).
exposedHeaders(HttpHeaders.SET_COOKIE)
// maxAge(1800)表明在1800秒内,不需要再发送预检验请求,可以缓存该结果
.maxAge(1800L);
}
};
}
}
方案三:拦截器Filter实现
@Component public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Credentials", "true");
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}