Spring Boot+VUE 前后端分离跨域配置
# CORS介绍:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS (opens new window)
# SpringBoot配置跨域
配置类型:org.springframework.web.servlet.config.annotation.WebMvcConfigurer
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS");
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# Access-Control-Allow-Credentials及 Access-Control-Allow-Origin配置
在阅读CORS介绍是发现如果一段介绍,针对需要附带身份凭证的请求的一个介绍,如下:
附带身份凭证的请求与通配符 ( Access-Control-Allow-Credentials: true)对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为“”。 这是因为请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为 http://foo.example,则请求将成功执行。
如上介绍所说和我们后端代码中的配置不太一致,猜想Spring做了处理,所以对这块的处理代码进行阅读,发现spring流程大致如下,确实帮我们处理了这种情况,如下
关键代码:
- 判断是否跨域请求
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.web.cors;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpMethod;
public abstract class CorsUtils {
public CorsUtils() {
}
public static boolean isCorsRequest(HttpServletRequest request) {
return request.getHeader("Origin") != null;
}
// 判断是否为预检请求
public static boolean isPreFlightRequest(HttpServletRequest request) {
return isCorsRequest(request) && HttpMethod.OPTIONS.matches(request.getMethod()) && request.getHeader("Access-Control-Request-Method") != null;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- org.springframework.web.cors.DefaultCorsProcessor 处理 Access-Control-Allow-Credentials: true 时 Access-Control-Allow-Origin * 问题
public boolean processRequest(@Nullable CorsConfiguration config, HttpServletRequest request, HttpServletResponse response) throws IOException {
if (!CorsUtils.isCorsRequest(request)) {
return true;
} else {
ServletServerHttpResponse serverResponse = new ServletServerHttpResponse(response);
if (this.responseHasCors(serverResponse)) {
logger.trace("Skip: response already contains \"Access-Control-Allow-Origin\"");
return true;
} else {
ServletServerHttpRequest serverRequest = new ServletServerHttpRequest(request);
if (WebUtils.isSameOrigin(serverRequest)) {
logger.trace("Skip: request is from same origin");
return true;
} else {
boolean preFlightRequest = CorsUtils.isPreFlightRequest(request);
if (config == null) {
if (preFlightRequest) {
this.rejectRequest(serverResponse);
return false;
} else {
return true;
}
} else {
return this.handleInternal(serverRequest, serverResponse, config, preFlightRequest);
}
}
}
}
}
protected boolean handleInternal(ServerHttpRequest request, ServerHttpResponse response, CorsConfiguration config, boolean preFlightRequest) throws IOException {
String requestOrigin = request.getHeaders().getOrigin();
String allowOrigin = this.checkOrigin(config, requestOrigin);
@Nullable
protected String checkOrigin(CorsConfiguration config, @Nullable String requestOrigin) {
return config.checkOrigin(requestOrigin);
}
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
35
36
37
38
39
40
41
42
43
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
35
36
37
38
39
40
41
42
43
3.org.springframework.web.cors.CorsConfiguration#checkOrigin
@Nullable
public String checkOrigin(@Nullable String requestOrigin) {
if (!StringUtils.hasText(requestOrigin)) {
return null;
} else if (ObjectUtils.isEmpty(this.allowedOrigins)) {
return null;
} else if (this.allowedOrigins.contains("*")) {
return this.allowCredentials != Boolean.TRUE ? "*" : requestOrigin;
} else {
Iterator var2 = this.allowedOrigins.iterator();
String allowedOrigin;
do {
if (!var2.hasNext()) {
return null;
}
allowedOrigin = (String)var2.next();
} while(!requestOrigin.equalsIgnoreCase(allowedOrigin));
return requestOrigin;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
##自定义拦截器时跨域相关配置时效处理
原因: 原因是请求经过的先后顺序问题,当请求到来时会先进入拦截器中,而不是进入Mapping映射中,所以返回的头信息中并没有配置的跨域信息。浏览器就会报跨域异常。
配置方式: 使用CorsFilter过滤器,如下:
private CorsConfiguration corsConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
* 请求常用的三种配置,*代表允许所有,当时你也可以自定义属性(比如header只能带什么,只能是post方式等等)
*/
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setMaxAge(3600L);
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig());
return new CorsFilter(source);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
编辑 (opens new window)
上次更新: 2021/10/08, 15:02:58