我們在從 UI 代碼庫進行跨域 API 呼叫時遇到了奇怪的問題,其中一種 Ajax 請求(vanilla JS)方式有效,但另一種方式(jQuery)無效。任何指標都會有所幫助。
跨域成功呼叫
let url = 'https://somedomain.com/test-api/links';
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = 'application/json';
xhr.onload = function () {
// Successful request
if (xhr.status == 200) {
console.log('success')
}
};
xhr.onerror = function () {
// Crossdomain request denied
if (xhr.status === 0) {
console.log(xhr.response)
}
};
xhr.crossDomain = true;
xhr.withCredentials = true;
xhr.send();
但是,使用以下代碼庫(jQuery),我們收到錯誤訊息說明 -:
從源“https://callerDomain.com”訪問“https://sourcedomain.com/test-api/links”的 XMLHttpRequest 已被 CORS 策略阻止:對預檢請求的回應未通過訪問控制檢查:回應中“Access-Control-Allow-Credentials”標頭的值為“”,當請求的憑據模式為“包含”時,該值必須為“真”。XMLHttpRequest 發起的請求的憑證模式由 withCredentials 屬性控制
.ajax({
url: "https://somedomain.com/test-api/links",
method: 'GET',
contentType: 'application/json',
dataType: "json",
crossDomain : true,
xhrFields: {
withCredentials: true
}
}).then((resp) => {
console.log(resp)
}).catch((err) => {
console.log(err)
});
sourcedomain.com 上的 Apache 配置
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header set Access-Control-Allow-Credentials true
Header always set Access-Control-Allow-Origin "https://callerDomain.com"
Header always set Access-Control-Allow-Headers "*"
更新: 由于以下組合無效,我將 apcahe 配置更新為
Header always set Access-Control-Allow-Headers "*"
Header set Access-Control-Allow-Credentials true
Apache 在 sourcedomain.com 上更新了配置
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header set Access-Control-Allow-Credentials true
Header always set Access-Control-Allow-Origin "https://callerDomain.com"
//for testing only
Header set Access-Control-Allow-Headers "Accept, Accept-CH, Accept-Charset, Accept-Datetime, Accept-Encoding, Accept-Ext, Accept-Features, Accept-Language, Accept-Params, Accept-Ranges, Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Request-Headers, Access-Control-Request-Method, Age, Allow, Alternates, Authentication-Info, Authorization, C-Ext, C-Man, C-Opt, C-PEP, C-PEP-Info, CONNECT, Cache-Control, Compliance, Connection, Content-Base, Content-Disposition, Content-Encoding, Content-ID, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range, Content-Script-Type, Content-Security-Policy, Content-Style-Type, Content-Transfer-Encoding, Content-Type, Content-Version, Cookie, Cost, DAV, DELETE, DNT, DPR, Date, Default-Style, Delta-Base, Depth, Derived-From, Destination, Differential-ID, Digest, ETag, Expect, Expires, Ext, From, GET, GetProfile, HEAD, HTTP-date, Host, IM, If, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Keep-Alive, Label, Last-Event-ID, Last-Modified, Link, Location, Lock-Token, MIME-Version, Man, Max-Forwards, Media-Range, Message-ID, Meter, Negotiate, Non-Compliance, OPTION, OPTIONS, OWS, Opt, Optional, Ordering-Type, Origin, Overwrite, P3P, PEP, PICS-Label, POST, PUT, Pep-Info, Permanent, Position, Pragma, ProfileObject, Protocol, Protocol-Query, Protocol-Request, Proxy-Authenticate, Proxy-Authentication-Info, Proxy-Authorization, Proxy-Features, Proxy-Instruction, Public, RWS, Range, Referer, Refresh, Resolution-Hint, Resolver-Location, Retry-After, Safe, Sec-Websocket-Extensions, Sec-Websocket-Key, Sec-Websocket-Origin, Sec-Websocket-Protocol, Sec-Websocket-Version, Security-Scheme, Server, Set-Cookie, Set-Cookie2, SetProfile, SoapAction, Status, Status-URI, Strict-Transport-Security, SubOK, Subst, Surrogate-Capability, Surrogate-Control, TCN, TE, TRACE, Timeout, Title, Trailer, Transfer-Encoding, UA-Color, UA-Media, UA-Pixels, UA-Resolution, UA-Windowpixels, URI, Upgrade, User-Agent, Variant-Vary, Vary, Version, Via, Viewport-Width, WWW-Authenticate, Want-Digest, Warning, Width, X-Content-Duration, X-Content-Security-Policy, X-Content-Type-Options, X-CustomHeader, X-DNSPrefetch-Control, X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto, X-Frame-Options, X-Modified, X-OTHER, X-PING, X-PINGOTHER, X-Powered-By, X-Requested-With"
對預檢請求的回應


uj5u.com熱心網友回復:
問題)
兩個請求不等價
對于通過 XHR 發送的,您只需設定回應的內容型別:
xhr.open("GET", url, true);
// ...
xhr.responseType = 'application/json';
但是,對于通過 jQuery 發送的請求,您將請求本身的內容型別設定為application/json:
.ajax({
// ...
method: 'GET',
contentType: 'application/json',
// ...
});
將通配符與憑據請求結合使用
的值application/json對一個請求的內容型別使得非簡單; 因此,您的瀏覽器會觸發預檢請求。但是,您正在回應此預檢請求
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
這是一個不兼容的組合。因此,CORS 預檢失敗,如瀏覽器錯誤訊息中所述。
總是以403狀態回應預檢請求
您的最新編輯顯示對預檢請求的回應狀態為403。但是,要使 CORS 預檢成功,狀態必須在2xx范圍內;請參閱我最近對此的另一個回答。
解決方案
- 要么不指定請求的內容型別以保持簡單,要么(最好)明確允許
Content-Type標頭中的Access-Control-Allow-Headers標頭而不是使用通配符。 - 確保您以
2xx狀態回應成功的預檢請求。請注意,由于預檢請求從不攜帶憑據,因此您應該在任何授權中間件之前處理此類請求。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/401533.html
標籤:javascript 阿贾克斯 科斯 xmlhttp请求
