跨域问题修复
跨域检测
F12 控制台输入以下命令验证apiUrl
fetch('apiUrl', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: location.href }), credentials: 'include' })
根据提示校验跨域配置问题
gateway 配置
globalcors: # 全局的跨域配置
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
# options请求 就是一种询问服务器是否浏览器可以跨域的请求
# 如果每次跨域都有询问服务器是否浏览器可以跨域对性能也是损耗
# 可以配置本次跨域检测的有效期maxAge
# 在maxAge设置的时间范围内,不去询问,统统允许跨域
corsConfigurations:
'[/**]':
allowedOrigins: "*" # 允许哪些网站的跨域请求
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 允许在请求中携带cookie
maxAge: 360000 # 本次跨域检测的有效期(单位毫秒)
# 有效期内,跨域请求不会一直发option请求去增大服务器压力
网关配置
@Configuration
public class CorsConfig {
/**
* 这里为支持的请求头,如果有自定义的header字段请自己添加
*/
private static final String ALLOWED_HEADERS = "Content-Type, Authorization, credential, X-XSRF-TOKEN, token, Admin-Token, App-Token";
private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD";
private static final String ALLOWED_ORIGIN = "xxx";
private static final String ALLOWED_EXPOSE = "*";
private static final String MAX_AGE = "18000L";
@Bean
public WebFilter corsFilter()
{
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
if (CorsUtils.isCorsRequest(request))
{
ServerHttpResponse response = ctx.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Credentials", "true");
if (request.getMethod() == HttpMethod.OPTIONS)
{
response.setStatusCode(HttpStatus.NO_CONTENT);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
}
后端接口配置跨域
@PostMapping("/test")
public R<?> test( HttpServletRequest req, HttpServletResponse res) {
String method = req.getMethod();
log.info("method = {}", method);
if(Objects.nonNull(req.getHeader("origin"))){
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Expose-Headers", "");
if("OPTIONS".equals(method)){
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
// res.setHeader("Access-Control-Max-Age", "600");
res.setHeader("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE");
res.setHeader("Content-Length", "0");
res.setStatus(204);
return R.ok();
}
}
{业务逻辑}
}
前端配置跨域
if (req.headers.origin) {
setHeader(res, {
'Access-Control-Allow-Origin': req.headers.origin,
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Expose-Headers': '',
})
// do not use the same cache if response allow origin is not *
if (res.getHeader('Access-Control-Allow-Origin') !== '*') {
appendHeader(res, 'Vary', 'Origin')
}
// preflight
if (req.method === 'OPTIONS') {
setHeader(res, {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Max-Age': '600',
'Access-Control-Allow-Methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', // default GET,POST
})
res.setHeader('Content-Length', '0');
res.status(204).end()
return
}
}