文章目录
前言
说明:项目使用的是Springboot 2.0 + Vue 3.0 ,权限框架使用的是 Spring-security + Jwt
一、跨域是什么?为什么要解决跨域?
跨域是浏览器的同源策略造成的,只要是域名、端口、协议有一不同,就会被当做是不同的域,之间的请求就被当做跨域操作。
设置同源限制主要是为了安全,如果没有同源限制存在浏览器中的cookie等其他数据可以任意读取,不同域下DOM任意操作,Ajax任意请求的话如果浏览了恶意网站那么就会泄漏这些隐私数据。
二、方式
1.过滤器方式:覆盖默认的CorsFilter来解决该问题
package com.boduo.config.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;
/**
* @Description:类描述
* @Author nanyi
* @Date 2021/1/28 9:19
**/
@Configuration
public class CorsConfig {
private CorsConfiguration config() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
// ① 设置你要允许的网站域名,如果全允许则设为 *
corsConfiguration.addAllowedOrigin("*");
// 新的springboot版本中,跨域配置需要将 addAllowedOrigin("*")换成addAllowedOriginPattern("*");即:corsConfiguration.addAllowedOriginPattern("*");
// 不然会报:When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of orig
// ② 如果要限制 HEADER 或 METHOD 请自行更改
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration( "/**", config() );
return new CorsFilter(source);
}
}
2.全局配置的方式
除了细粒度、基于注释的配置之外,您还可能需要定义一些全局CORS配置,这类似于使用筛选器,但可以声明为Spring MVC并结合细粒度@CrossOrigin配置。默认情况下,所有origins and GET, HEAD and POST methods是允许的。
@EnableWebMvc
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
//每次调用registry.addMappin可以添加一个跨域配置,需要多个配置可以多次调用registry.addMapping
registry.addMapping("/**")
.allowedOrigins("*") //放行哪些原始域
.allowedMethods("PUT", "DELETE","POST", "GET") //放行哪些请求方式
.allowedHeaders("header1", "header2", "header3") //放行哪些原始请求头部信息
.exposedHeaders("header1", "header2") //暴露哪些头部信息
.allowCredentials(false) //是否发送 Cookie
.maxAge(3600);
}
}
3.方法或者类上标注@CrossOrigin注解
- 接口方法上标注org.springframework.web.bind.annotation.CrossOrigin注解,如下test1接口上标注了@CrossOrigin注解,这个接口就支持跨域访问,@CrossOrigin注解中含有更详细的配置,这里就不细说了
- 也可以在类上标注@CrossOrigin注解,那么这个类中所有接口会支持跨域访问
- 也可同时在类和方法上标注@CrossOrigin注解,最后方法上的跨域访问会取合并后的配置
@RestController
public class CorsController {
@RequestMapping("/cors/test1")
@CrossOrigin
public List<String> test1() {
return Arrays.asList("q","w","e","r","t");
}
}
4.设置SpringSecurity允许OPTIONS请求访问
.antMatchers(HttpMethod.OPTIONS).permitAll()//跨域请求会先执行一次option请求
补充:为什么每次请求之前要发送一个OPTIONS请求?
原来,浏览器在某些请求中,在正式通信前会增加一次HTTP查询请求,称为"预检"请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
所以本地环境请求接口的时候,每次请求接口之前都会多一次OPTIONS请求。
总结
成为一个小胖子,没事摸摸小肚子~