Spring boot设置跨域请求的多种方式

标签: Springboot 分类: Java 创建时间:2019-03-05 07:48:13 更新时间:2024-11-15 10:49:43

1.SpringBoot跨域设置

主要有四种方式:

  • 方式1:返回新的CorsFilter;
  • 方式2:重写WebMvcConfigurer;
  • 方式3:使用注解(@CrossOrigin)
  • 方式4:手工设置响应头(HttpServletResponse )。

2.实现WebMvcConfigurer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Configuration
@ControllerAdvice
public class MvcConfig implements WebMvcConfigurer {
//跨域设置
@Override
//重写父类提供的跨域请求处理的接口
public void addCorsMappings(CorsRegistry registry) {
//添加映射路径
registry.addMapping("/**")
//放行哪些原始域
.allowedOrigins("*")
//是否发送Cookie信息
.allowCredentials(true)
//放行哪些原始域(请求方式)
.allowedMethods("GET","POST", "PUT", "DELETE")
//放行哪些原始域(头部信息)
.allowedHeaders("*");
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
//.exposedHeaders("Header1", "Header2");
}
}

这种方式的缺点是,假如spring boot配置了拦截器(为了实现权限验证),假如用户身份不通过,拦截器方法preHandle一般会返回false,阻止拦截器继续执行,但也同时把上面设置的处理跨域的拦截器禁止掉,自然也就完成不了拦截器。解决方式是下面这种方式。如果重写WebMvcConfigurer,Idea会出现这个问题“No interface expected here”。

问题出在要使用implements,而不是 extends。

参考文章:
1.SpringBoot—-跨域配置
2.springboot 解决跨域
3.Spring Security的WebMvcConfigurerAdapter已过时
4.WebMvcConfigurerAdapter已过时 (这里解决WebMvcConfigurerAdapter过时问题)
5.SpringBoot配置Cors解决跨域请求问题
6.[Spring Boot配置接口 WebMvcConfigurer}(https://blog.csdn.net/fmwind/article/details/81235401)
7.Spring Boot 2.4.5 跨域解决 这篇文章解决了问题
8.springboot 跨域处理无效填坑篇 第一种 @CrossOrigin,第二种 WebMvcConfigurer 都失败了,使用了 CorsFilter实现Filter,验证成功
9.SpringBoot配置CORS解决跨域时的坑 这个也是用了CorsFilter实现的,但是我遇到的问题是 UrlBasedCorsConfigurationSource无法转换为org.springframework.web.cors.CorsConfigurationSource

3.自定义filter

通过定义自己的filter,代替原先的拦截器。一个http请求,先走filter,到达servlet后才进行拦截器的处理,如果我们把cors放在filter里,就可以优先于权限拦截器执行。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*");
config.setAllowCredentials(true);
config.addAllowedMethod("*");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
}

这里要注意的是CorsFilter,引入的包是org.springframework.web.filter.CorsFilter,而不是apache那个。

4.自定义FilterRegistrationBean

这种和第二种也是类似的,行不行,没实验。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration
public class CorsConfig {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// 设置你要允许的网站域名,如果全允许则设为 *
config.addAllowedOrigin("http://localhost:4200");
// 如果要限制 HEADER 或 METHOD 请自行更改
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
// 这个顺序很重要哦,为避免麻烦请设置在最前
bean.setOrder(0);
return bean;
}
}

5.扩展OncePerRequestFilter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class CorsFilter extends OncePerRequestFilter {

static final String ORIGIN = "Origin";

protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {

String origin = request.getHeader(ORIGIN);

response.setHeader("Access-Control-Allow-Origin", "*");//* or origin as u prefer
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "PUT, POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "content-type, authorization");

if (request.getMethod().equals("OPTIONS"))
response.setStatus(HttpServletResponse.SC_OK);
else
filterChain.doFilter(request, response);

}
}
@Bean
public CorsFilter corsFilter() throws Exception {
return new CorsFilter();
}

http
.addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
.headers()
.cacheControl();

参考文档:
1.SpringMVC的Interceptor和Cors冲突
2.springboot设置cors跨域请求的两种方式
3.为什么出现OPTIONS?SpringBoot接口跨域解决方案 原来浏览器会在发送真正请求之前,先发送一个方法为OPTIONS的预检请求 Preflighted requests 这个请求是用来验证本次请求是否安全的,而且并不是所有请求都会发送,需要符合以下条件:1.请求方法不是GET/HEAD/POST。2.POST请求的Content-Type并非application/x-www-form-urlencoded, multipart/form-data, 或text/plain。3.请求设置了自定义的header字段

问题

(1) allowedOrigins cannot contain the special value “
在设置 allowCredentials的时候,出现了这个错误: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 origins, list them explicitly or consider using “allowedOriginPatterns” instead.

1
2
3
4
5
6
7
8
9
10
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.setAllowCredentials(true);
// ...
}
}

【解决方法】
将 addAllowedOrigin 改为 addAllowedOriginPattern;

1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 主要是这里
config.addAllowedOriginPattern("*");
config.setAllowCredentials(true);
// ...
}
}
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。