前后端分离——跨域问题
早睡蛋 8/2/2022 跨域前后端分离SpringBoot
# 问题概述
通常在使用SpringBoot与Vue等前后端中,会出现跨域的问题。
总结了以下情况的问题:
- 有没开启相关注解
- 没有配置相关跨域配置类
- 配置了跨域配置但是仍然报错
- .....
# 解决方案
1、最基本的就是在控制层上加上@CrossOrigin
注解,@CrossOrigin
注解里面定义了基本的跨域网关参数。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ORIGINS = {"*"};
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ALLOWED_HEADERS = {"*"};
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
boolean DEFAULT_ALLOW_CREDENTIALS = false;
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
long DEFAULT_MAX_AGE = 1800;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2、配置跨域配置类
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowCredentials(true);
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
这是有时会出现以下报错:
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
这是由于SpringBoot中版本升级了导致不一致的原因,按照提示修改如下即可:
allowedOriginPatterns("*")
1
3、经过上述的方案,基本能解决大部分问题,如果还是报错,则修改配置类,如下:
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOriginPattern("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setMaxAge(3600L); // 预检请求的有效期,单位为秒。
corsConfiguration.setAllowCredentials(true);// 是否支持安全证书(必需参数)
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 另外
在Shiro中如果遇到跨域问题,并且是OPTIONS请求的问题,那么编写配置类,对OPTIONS的请求进行放行即可:
public class CORSAuthenticationFilter extends FormAuthenticationFilter {
// 直接过滤可以访问的请求类型
private static final String REQUET_TYPE = "OPTIONS";
public CORSAuthenticationFilter() {
super();
}
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (((HttpServletRequest) request).getMethod().toUpperCase().equals(REQUET_TYPE)) {
return true;
}
return super.isAccessAllowed(request, response, mappedValue);
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletResponse res = (HttpServletResponse)response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setStatus(HttpServletResponse.SC_OK);
res.setCharacterEncoding("UTF-8");
PrintWriter writer = res.getWriter();
writer.write(JSONObject.toJSONString(LoginEnums.NO_LOGIN.getResultResponseVo()));
writer.close();
return false;
}
}
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
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
然后在Shiro的配置类中添加配置类:
LinkedHashMap<String, Filter> filtersMap = new LinkedHashMap<>();
// 自定义跨域前后端分离验证过滤器
filtersMap.put("corsAuthenticationFilter", new CORSAuthenticationFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
1
2
3
4
2
3
4