解决跨域的五种方法
1、CorsFilter
新建一个类
-
@Configuration
-
public
class
CorsConfig {
-
@Bean
-
public CorsFilter
corsFilter
() {
-
//1. 添加 CORS配置信息
-
CorsConfiguration
config
=
new
CorsConfiguration();
-
//放行哪些原始域
-
//springboot版本为2.4.0以前写法
-
config.addAllowedOrigin(
"*");
-
//springboot版本为2.4.0以后写法
-
config.setAllowedOriginPatterns(Collections.singletonList(
"*"));
-
-
//查看项目的springboot版本
-
//System.out.println(SpringBootVersion.getVersion());
-
-
-
//是否发送 Cookie
-
config.setAllowCredentials(
true);
-
//放行哪些请求方式
-
config.addAllowedMethod(
"*");
-
//放行哪些原始请求头部信息
-
config.addAllowedHeader(
"*");
-
//暴露哪些头部信息
-
config.addExposedHeader(
"*");
-
//2. 添加映射路径
-
UrlBasedCorsConfigurationSource
corsConfigurationSource
=
new
UrlBasedCorsConfigurationSource();
-
corsConfigurationSource.registerCorsConfiguration(
"/**",config);
-
//3. 返回新的CorsFilter
-
return
new
CorsFilter(corsConfigurationSource);
-
}
-
}
2、重写 WebMvcConfigurer
-
@Configuration
-
public
class
CorsConfig
implements
WebMvcConfigurer {
-
@Override
-
public
void
addCorsMappings
(CorsRegistry registry) {
-
registry.addMapping(
"/**")
-
//是否发送Cookie
-
.allowCredentials(
true)
-
//放行哪些原始域
-
.allowedOrigins(
"*")
-
.allowedMethods(
new
String[]{
"GET",
"POST",
"PUT",
"DELETE",
"OPTIONS",
"PATCH"})
-
.allowedHeaders(
"*")
-
.exposedHeaders(
"*");
-
}
-
}
3、使用注解
-
@RestController
-
@CrossOrigin(origins = "*")
-
public
class
CorsController {
-
@RequestMapping("/cors")
-
@CrossOrigin(origins = "*")
-
public String
cors
() {
-
return
"cors";
-
}
-
}
-
4、手动设置响应头
-
@RequestMapping("/cors")
-
public String
cors
(HttpServletResponse response) {
-
response.addHeader(
"Access-Allow-Control-Origin",
"*");
-
return
"cors";
-
}
5、使用自定义filter
-
import org.springframework.context.annotation.Configuration;
-
import javax.servlet.*;
-
import javax.servlet.annotation.WebFilter;
-
import javax.servlet.http.HttpServletResponse;
-
import java.io.IOException;
-
@WebFilter(filterName = "CorsFilter ")
-
@Configuration
-
public
class
CorsFilter
implements
Filter {
-
@Override
-
public
void
doFilter
(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
-
HttpServletResponse
response
= (HttpServletResponse) res;
-
response.setHeader(
"Access-Control-Allow-Origin",
"*");
-
response.setHeader(
"Access-Control-Allow-Credentials",
"true");
-
response.setHeader(
"Access-Control-Allow-Methods",
"POST, GET, PATCH, DELETE, PUT, OPTIONS");
-
response.setHeader(
"Access-Control-Max-Age",
"3600");
-
response.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept");
-
chain.doFilter(req, res);
-
}
-
}
模拟跨域
跨域的拦截是浏览器行为,所以后端开发的时候不会遇到这个问题,只有在联调的时候才会发现,这种问题前端、后端都可以解决。前端通过代理请求同一域的一个接口,然后转发到后端。后端则通过在Response Header设置值解决。而后端本地测试跨域配置是否生效时比较麻烦,因为是浏览器问题,发布到测试环境流程长,所以需要本地也能复现跨域问题,其实也比较简单,只不过需要百度一些前端代码[狗头]
首先,先随便找一个网站,然后在Console向本地发送Http请求就能模拟跨域了。

-
// 普通请求
-
var
xhr
=
new
XMLHttpRequest();
-
xhr.open(
'OPTIONS',
'http://127.0.0.1:8080/test1');
-
xhr.send();
-
xhr.onload = function(e) {
-
var
xhr
= e.target;
-
console.log(xhr.responseText);
-
}
-
-
// GET请求
-
var
xhr
=
new
XMLHttpRequest();
-
xhr.open(
'GET',
'http://127.0.0.1:8080/test1?a=1');
-
xhr.send();
-
xhr.onload = function(e) {
-
var
xhr
= e.target;
-
console.log(xhr.responseText);
-
}
-
-
// 携带header
-
var
xhr
=
new
XMLHttpRequest();
-
xhr.open(
'GET',
'http://127.0.0.1:8080/test1?a=1');
-
xhr.setRequestHeader(
'content-type',
'application/json');
-
xhr.setRequestHeader(
'signature',
'gaejhgkaehguiaehiuavoihvoihviehviehiohao');
-
xhr.send();
-
xhr.onload = function(e) {
-
var
xhr
= e.target;
-
console.log(xhr.responseText);
-
}
-
-
// POST请求
-
var
xhr
=
new
XMLHttpRequest();
-
xhr.open(
'POST',
'http://127.0.0.1:8080/test1?a=1');
-
xhr.setRequestHeader(
'content-type',
'application/json');
-
xhr.setRequestHeader(
'signature',
'gaejhgkaehguiaehiuavoihvoihviehviehiohao');
-
xhr.send(
"{a:1,b:2}");
-
xhr.onload = function(e) {
-
var
xhr
= e.target;
-
console.log(xhr.responseText);
-
}
跨域问题踩过的坑
这些问题主要是网上代码都是抄来抄去,有一些人抄的时候删了一些或者copy漏了,导致代码不全,然后又因为浏览器的一些机制导致了还是存在跨域问题,坑了后面的人。
踩坑一:没有允许OPTIONS请求跨域
比如用上面的方案二来处理跨域问题

乍一看没有什么问题,只是不支持OPTIONS请求,但是浏览器在处理跨域请求的时候,会先发送一个OPTIONS请求去检测服务是否允许跨域请求,然后再去请求服务要数据之类的。所以这里根本没解决,联调时还是会有跨域问题。
踩坑二:没有允许Credentials
场景:后端不允许前端传递用户凭证,但是前端请求的时候带上了,这时浏览器也会报跨域错误
用户凭证是用户登录之后,服务器下发的一些凭证,如cookie。在跨域请求中,浏览器并不会把cookie携带上,但是可以通过js代码携带上。
使用上面方案一,不允许用户凭证


转载:https://blog.csdn.net/qq_41084438/article/details/128703767
查看评论