一、跨域CORS是什么
当一个资源从与该资源本身所在的服务器的域或端口不同的域或不同的端口请求一个资源时,浏览器会发起一个跨域HTTP 请求。出于安全考虑,浏览器会限制从脚本内发起的跨域HTTP请求或者拦截了服务器返回内容。例如,XMLHttpRequest 和 Fetch 遵循同源策略。因此,使用 XMLHttpRequest或 Fetch 的Web应用程序只能将HTTP请求发送到其自己的域;这种安全机制是为避免出现类似CSRF 跨站攻击等问题。
二、实现CORS
根据CORS的定义和W3C相关规范,明白了跨域的关键问题是在于服务端是否允许;而服务端是通过W3C所规定的相关CORS heades来实现的;相关headers如下:
Access-Control-Allow-Origin:*
该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
Access-Control-Allow-Methods: POST, GET, OPTIONS
该字段可选。表明服务器允许客户端使用POST, GET 和 OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
该字段可选。表明服务器允许请求中携带字段X-PINGOTHER 与 Content-Type。
Access-Control-Max-Age: 86400
表明该响应的有效时间为86400 秒,也就是 24 小时。在有效时间内,浏览器无须为同一请求再次发起预检请求,可以减少发送请求的次数,减少系统部分压力。
Access-Control-Allow-Credentials: true
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。
三、实现一个跨域
@Configuration
public class CorsConfig {
private static final StringALLOWED_HEADERS ="x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client";
// private static final String ALLOWED_HEADERS = "*";//使用*号,在firefox浏览器无法跨域请求
private static final StringALLOWED_METHODS ="*";
private static final StringALLOWED_ORIGIN ="*";
private static final StringALLOWED_Expose ="*";
// private static final String MAX_AGE = "18000L";
@Bean
public WebFiltercorsFilter() {
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-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
// headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
headers.add("Access-Control-Expose-Headers", ALLOWED_Expose);
headers.add("Access-Control-Allow-Credentials", "true");
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
}
四、测试跨域请求:
在谷歌浏览器中实现了跨域请求成功,但是在火狐浏览器中就提示跨域失败,最后经过测试把private static final String ALLOWED_HEADERS = "*"; 替换为 private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client"; 则在火狐浏览器中可以跨域请求成功。
总结:需要将ALLOWED_HEADERS = "*";替换为 "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client";
网友评论