一无埃、跨域CORS是什么
當(dāng)一個(gè)資源從與該資源本身所在的服務(wù)器的域或端口不同的域或不同的端口請(qǐng)求一個(gè)資源時(shí)蜒谤,瀏覽器會(huì)發(fā)起一個(gè)跨域HTTP 請(qǐng)求击费。出于安全考慮赋兵,瀏覽器會(huì)限制從腳本內(nèi)發(fā)起的跨域HTTP請(qǐng)求或者攔截了服務(wù)器返回內(nèi)容笔咽。例如霹期,XMLHttpRequest 和 Fetch 遵循同源策略历造。因此甩十,使用 XMLHttpRequest或 Fetch 的Web應(yīng)用程序只能將HTTP請(qǐng)求發(fā)送到其自己的域;這種安全機(jī)制是為避免出現(xiàn)類似CSRF 跨站攻擊等問題吭产。
二臣淤、實(shí)現(xiàn)CORS
根據(jù)CORS的定義和W3C相關(guān)規(guī)范姓蜂,明白了跨域的關(guān)鍵問題是在于服務(wù)端是否允許;而服務(wù)端是通過W3C所規(guī)定的相關(guān)CORS heades來實(shí)現(xiàn)的滩字;相關(guān)headers如下:
Access-Control-Allow-Origin:*
該字段是必須的。它的值要么是請(qǐng)求時(shí)Origin字段的值,要么是一個(gè)*诀蓉,表示接受任意域名的請(qǐng)求。
Access-Control-Allow-Methods: POST, GET, OPTIONS
該字段可選沥曹。表明服務(wù)器允許客戶端使用POST, GET 和 OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
該字段可選。表明服務(wù)器允許請(qǐng)求中攜帶字段X-PINGOTHER 與 Content-Type。
Access-Control-Max-Age: 86400
表明該響應(yīng)的有效時(shí)間為86400 秒贵试,也就是 24 小時(shí)。在有效時(shí)間內(nèi),瀏覽器無須為同一請(qǐng)求再次發(fā)起預(yù)檢請(qǐng)求施符,可以減少發(fā)送請(qǐng)求的次數(shù),減少系統(tǒng)部分壓力。
Access-Control-Allow-Credentials: true
該字段可選普筹。它的值是一個(gè)布爾值,表示是否允許發(fā)送Cookie。
三蜒车、實(shí)現(xiàn)一個(gè)跨域
@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 = "*";//使用*號(hào)嬉挡,在firefox瀏覽器無法跨域請(qǐng)求
? ? 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);
? ? ? ? };
? ? }
}
四、測(cè)試跨域請(qǐng)求:
在谷歌瀏覽器中實(shí)現(xiàn)了跨域請(qǐng)求成功,但是在火狐瀏覽器中就提示跨域失敗,最后經(jīng)過測(cè)試把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"; 則在火狐瀏覽器中可以跨域請(qǐng)求成功。
總結(jié):需要將ALLOWED_HEADERS = "*";替換為 "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client";