(舊版) 跨域qwq


因為blog標題原因, 本文重新發布了.

Title/ 瀏覽器跨域(CrossOrigin)請求的原理, 以及解決方案詳細指南 #flight.Archives011

序:
最近看到又有一波新的創作活動了, 官方給出的話題中有一個"為什么XHR不能跨域請求資源", 看起來像一道很簡單的面試題哈哈哈
作為前端愛好者, 不妨借此機會研究一下跨域, 總結一篇文章出來. 於是我就安排了flight.A011的FocusList#寫作計划.

簡介:
一篇最簡潔高效的跨域請求指南 made with ❤ by 忘我思考

注:

  1. 本文中XHR表示 XMLHttpRequest 對象.
  2. CORS表示Cross-origin resource sharing, 譯為跨域資源共享.
  3. 請求頭即 Request Headers, 響應頭即 Response Headers.

Tag/ 瀏覽器跨域(CORS)限制介紹: 為什么要限制XHR跨域請求, 如何觸發跨域限制

大佬們可以直接看下一章解決方案, 這里會解釋得詳細一點方便新手入門(誰都曾是萌新嘛), 不了解CORS的來這補補課吧~

跨域, 就是站A的請求要訪問站B的服務器.
如果 協議(protocol), 域名(domain), 端口(port) 三者有任意一處不同, 瀏覽器就認為這是兩個不同的網站, 會觸發跨域安全限制.

詳細的說, 就是:
[https://][example.com][:80]/path?query#heading-1
只有打方括號內的內容完全一致才是"同源", 也就是說同源請求URL中只有端口后的內容是可以不一致的, 否則就是跨域
請注意: https協議的默認端口是443, http協議默認端口是80. 默認端口可以省略不寫.
也就是說 https://example.com:443/... 和 https://example.com/... 是同源, http同理.

->> 為什么瀏覽器要有跨域限制

設想這樣的場景:
我是不知名小Blog主, 你現在在訪問我的博客網站, 然后我突發奇想, 想要用自動JS程序發送請求到 weibo 的服務器, 讓你自動關注我的微博.
如果這能實現, 那瀏覽器就太不安全了, 網站主可以在后台做很多危險請求(如獲取你在 weibo 的登錄信息等).
所以瀏覽器都有一個跨域限制, 阻止不安全的第三方內容請求.

舉個例子:

如果我在Segmentfault官網的Console訪問我的博客園首頁, 就會觸發XHR跨域限制, 禁止讀取返回內容.

而另一個情景:
你是一個小站長, 在網站使用Vue.js, 於是添加了一個CDN腳本(如 unpkg 等)
結果瀏覽器錯誤的因為跨域限制自動攔截請求導致你無法使用CDN腳本.
這顯然是不合理的, 所以現在的瀏覽器都會智能根據對方(網站B)的 響應頭 中的 Access-Control-Allow-Origin屬性, 來判斷你是否可以讀取對方返回的內容.
比如 unpkg 就把 Access-Control-Allow-Origin 屬性設為了 *, 方便外域調用CDN.

像React也建議你驗證CDN的請求頭屬性, 避免使用出現跨域限制問題.

也就是說, 你能不能訪問第三方資源, 其實是由對方(響應頭)決定的(這其實也是合理的, 按道理請求別人的東西就要經過允許呀).
對方服務器可以通過你的 cookie referer請求頭 參數來判斷請求的安全性, 決定是否返回對應內容.
注意: 純前端是不能纂改 referer 請求頭的, 否則會報錯.

->> 瀏覽器對請求的詳細划分方法: 簡單請求和復雜請求

不過瀏覽器的跨域限定其實有詳細的划分, 這里有必要提到一下:
請求分為 簡單請求復雜請求 兩種.
對於 簡單請求, 要滿足以下所有條件("與"關系).

  1. 請求方法是 GET, POST, HEAD 之一.
  2. 人為設置的請求頭不超過以下屬性: Accept, Accept-Language, Content-Language.
  3. Content-Type 屬性值是 text/plain, multipart/form-data, application/x-www-form-urlencoded 之一.
  4. 請求中的任意 XMLHttpRequestUpload 對象均沒有注冊任何事件監聽器; XMLHttpRequestUpload 對象可以使用 XMLHttpRequest.upload 屬性訪問.
  5. 請求中沒有使用 ReadableStream 對象.

其中前3點比較常用. 如果請求不滿足以上5個條件的任意之一, 則是復雜請求.

瀏覽器區分 簡單請求復雜請求 是為了兼容表單(form), 因為歷史上表單一直可以發出跨域請求.

->> XHR請求在瀏覽器里是如何被發出去的? 瀏覽器對簡單請求和復雜請求的不同處理方式

這里我覺得阮一峰的文章已經寫得很好了(在文末有鏈接), 所以, 如有雷同(不對, 就是雷同)... 不要覺得我是在抄襲, 只是按照他的創意共享3.0許可證合法借鑒哈.

  1. 瀏覽器對簡單請求的處理方式!
    如果一個XHR滿足簡單請求的所有判定, 那它會被這樣發出去:

    // 直接發送包含Origin請求頭的XHR請求到對方服務器
    瀏覽器會自動在頭信息之中, 添加一個Origin字段.
    如: Origin: http://api.gold.xitu.io (現在掘金被字節收取就變味了, 好懷念Ming在的時間啊...)
    Origin是"起源"的意思, 包含協議 + 域名 + 端口, 會告訴對方請求是從哪個源發出的.
    如果Origin指定的源不在許可范圍內(比如在cnblogs中添加訪問Bilibili的代碼), 對方會返回一個不包含Access-Control-Allow-Origin的響應頭, 
    瀏覽器就知道出錯了, 從而拋出一個錯誤, 被XMLHttpRequest的onerror回調函數捕獲. 
    注意: 這種錯誤無法通過狀態碼識別, 因為HTTP回應的狀態碼有可能是200.
    
    如果Origin指定的域名在許可范圍內, 服務器返回的響應, 會多出幾個頭信息字段:
    Access-Control-Allow-Origin: http://api.bbb.com
    Access-Control-Allow-Credentials: true
    Access-Control-Expose-Headers: FooBar
    上面這些以 Access-Control- 開頭的字段, 都表示對方服務器對請求的訪問限制.
    
    下面介紹一下這三個屬性: 
    1. Access-Control-Allow-Origin(必須屬性): 可以是URL, 表示對請求時Origin字段的值的限制, 也可以是 *, 表示接受任意域名的請求, 像CDN代碼存儲服務之類的.
    2. Access-Control-Allow-Credentials(可選): 一個布爾值, 只能為true, 表示是否允許發送Cookie. 默認情況下(不填該屬性), 則Cookie不包括在跨域請求之中.
    3. Access-Control-Expose-Headers(可選): 跨域請求時, XHR對象的getResponseHeader()方法只能拿到6個基本字段: Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma. 如果想拿到其他字段, 必須在Access-Control-Expose-Headers中指定. 上面的例子指定getResponseHeader('FooBar')可以返回FooBar字段的值.
    
    ->> Details: withCredentials 屬性
    上面說到, 跨域請求默認不發送Cookie和HTTP認證信息. 如果要把Cookie發到服務器, 一方面要服務器同意, 指定Access-Control-Allow-Credentials字段為true.
    另一方面, 網站主必須在AJAX請求中打開withCredentials屬性. 像這樣:
    
    var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
    
    否則, 即使服務器同意發送Cookie, 瀏覽器也不會發送. 這種情況下服務器即使要求設置Cookie, 瀏覽器也不會處理. 
    
    但是, 如果省略withCredentials設置, 有的瀏覽器還是會一起發送Cookie. 這時, 可以顯式關閉withCredentials:
    xhr.withCredentials = false;
    
    需要注意的是, 如果要發送Cookie, Access-Control-Allow-Origin就不能設為星號, 必須指定明確的, 與請求網頁一致的域名. 同時, Cookie依然遵循同源政策, 只有用服務器域名設置的Cookie才會上傳, 其他域名的Cookie並不會上傳, 且(跨域的)原網頁代碼中的document.cookie也無法讀取對方服務器域名下的Cookie.
    
  2. 瀏覽器對復雜請求的處理方式!

    // 先發送預檢請求(preflight), 請求通過后, 發送XHR到對方服務器
    瀏覽器會先詢問服務器, 當前網頁所在的域名是否在服務器的許可名單之中, 以及可以使用哪些HTTP動詞和頭信息字段. 只有得到肯定答復, 瀏覽器才會發出正式的XMLHttpRequest請求, 否則就報錯.
    
    來了, 這是一段JS代碼!
    var url = 'http://api.aaa.com/cors';
    var xhr = new XMLHttpRequest();
    xhr.open('PUT', url, true);
    xhr.setRequestHeader('X-Custom-Header', 'value');
    xhr.send();
    
    可以看到使用了 PUT 方法, 還人為設置了X-Custom-Header請求頭, 所以這是個復雜請求qwq...
    
    所以瀏覽器會發送一個預檢請求, 預檢請求的請求頭像這樣:
    OPTIONS /cors HTTP/1.1
    Origin: http://api.bbb.com
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: X-Custom-Header
    Host: api.aaa.com
    ...(以及一些更多的無關請求頭)
    
    預檢請求使用了 OPTIONS 方法, 表示這個請求是用來詢問的. 請求頭中, 關鍵字段是Origin, 表示請求來自哪個源.
    而 Access-Control-Request-Method 和 Access-Control-Request-Headers 你一看就明白是什么了, 分別是請求方法和人為設置了哪些屬性.
    
    服務器受到預檢請求后, 判斷請求頭是否OK, 如果OK就可以做出回應啦!
    響應頭中關鍵信息是這幾個:
    Access-Control-Allow-Origin: http://api.bbb.com
    Access-Control-Allow-Methods: GET, POST, PUT
    Access-Control-Allow-Headers: X-Custom-Header
    
    解釋一下~
    1. Access-Control-Allow-Origin: 表示允許的請求源, 也可以是*表示隨便什么網站.
    2. Access-Control-Allow-Methods: 就是允許的方法啊!
    3. Access-Control-Allow-Headers: 允許設置的請求頭參數.
    
    好了, 那如果服務器不同意預檢請求怎么辦呢~
    
    會返回一個正常的HTTP回應, 但是沒有任何CORS相關的頭信息字段. 這時,瀏覽器就認為, 服務器不同意預檢請求.
    因此觸發一個錯誤, 被XMLHttpRequest對象的onerror回調函數捕獲. 
    控制台會打印出如下的報錯信息:
    
    XMLHttpRequest cannot load http://api.aaa.com.
    Origin http://api.bbb.com is not allowed by Access-Control-Allow-Origin.
    
    服務器回應的其他CORS相關字段如下:
    Access-Control-Allow-Methods: GET, POST, PUT //所有支持的方法
    Access-Control-Allow-Headers: X-Custom-Header //如果瀏覽器請求包括Access-Control-Request-Headers字段, 則Access-Control-Allow-Headers字段是必需的, 表示支持的所有請求頭字段.
    Access-Control-Allow-Credentials(可選): true //也是表示Cookie
    Access-Control-Max-Age(可選): 1728000 //表示本次預檢請求的有效期, 單位為秒. 比如這個就設定了本次請求有效期是20天(1728000秒), 期間不再次發送請求.
    

->> 案例: 解決一個博客音樂播放器的跨域問題

瀏覽器的安全限制其實也不是完美無缺的, 前端的話如果不涉及驗證碼, 登錄, 加密之類的復雜操作, 通過一些技術手段想要突破跨域限制, 也不是沒有可能.
無后端支持也是可以實現跨域的, 不過一般要在用戶知情的情況下配合操作.
其實就是你可以實現一些跨域請求, 但是是否能夠獲取請求內容, 本來是由對方服務器請求頭決定的, 現在決定權在於用戶.
比如你想要在你的博客中添加一個音樂播放器, 播放QQ音樂的內容.
而眾所周知, 騰訊那邊的盜鏈(可以理解為跨域)限制是很強的!
所以一般我的實現是配合后端, 也就是訪問QQ音樂網址, 把音樂通過瀏覽器控制台Network欄獲取請求資源URL下載保存到自己的服務器.
然后直接訪問自己的服務器獲取音樂資源(QQ音樂一般是m4a, 網易一般是mp3, 不過順便一提網易取消了盜鏈保護, 所以一般可以直接用網易服務器, 只是有的音樂有版權保護就不能外域播放了).
而如果要純前端實現跨域音樂播放則可以使用 <iframe>, Chrome參數纂改, Chrome插件等方法來實現盜鏈.

這些《神奇》的方法也就是下一章會詳細介紹的內容啦~ [奸笑]

Tag/ 重頭戲開始了! 突破跨域限制的9種解決方案

  1. 使用 iframe 實現
    iframe 標簽可以將跨域內容嵌入你的網頁, 比如在博客中添加一個Bilibili視頻 或者 Codepen Demo的 iframe.
    不過 iframe 有兩個缺點:

    1. 很多服務器會直接拒絕跨域 iframe 請求,
    2. 跨域訪問 iframe 中的內容會遭到限制qwq.
      放幾張圖體會一下:

    如果在阮一峰的Blog中插入 iframe(cnblogs博文), 會被拒絕qwq...

    而如果在站內插入iframe則沒有問題, 看來博客園為了安全考慮目前關閉了跨域請求.

    而Bilibili就比較開放了, 目前可以插入iframe.

    不過如果你想通過iframe讀取或者篡改Bilibili網頁的內容也是不可以的啦~

    所以這終究只是一個向用戶"展示內容"的方法而已, 限制很多, 如果要讀取/篡改內容, 還是得同源才行~

  2. 使用CORS方法(跨域資源共享)
    這個方法也就是第一章中介紹的, 很詳細了. 不用再重復一遍啦.

    但是這種方法也是受到對方服務器的種種限制, 不能為所欲為qwq...

  3. 搞一個瀏覽器插件配合(終極大招, 直接無視跨域限制)
    嘿嘿嘿! 沒想到吧! 竟然還有這種方法?!
    網上這方面的文章一般都不會想到有這種神奇也是非常強大的方法, 不過這也是非常實用的.
    如果要我來, 很可能會采用這種方法, 可以不用后端支持進行跨域!
    如果你的網站面向的對象主要是愛好破解的極客/有探索精神的玩家, 可以向他們推薦你的Chrome插件, 或者是一段油猴腳本.
    比如讓用戶簡單的copy&paste添加一段你的油猴(TemperMonkey)腳本, 就可以實現跨域請求啦!
    (現在油猴/Chrome插件在極客/開發者手里也已經很普及了吧~, 想想你裝了多少插件...
    (當然一個都沒裝的勿噴!

    不過現在Chrome插件那么多, 可是你... 能不能獨立開發一個擴展插件呢? 恐怕很難吧...
    (其實如果你懂前端, 插件開發也不難, 只要了解Chrome插件專門的一些方法就行了.
    那么這里就簡單介紹一下實現方法, 如果你想開發一個完整實用的插件, 網上也有不少文檔了. (Chrome Developer中也有詳細的介紹

    不如先學習一下別人是怎么玩的. 我們隨便打開一個別人開發的Chrome插件的文件夾(我打開的是Tempermonkey), 是這幅景象:

    其中有一個 manifest.json 文件, 和你的插件支不支持跨域密切相關, 比如油猴的長這樣:

    {
    "background": {
    "page": "background.html"
    },
    "browser_action": {
    "default_icon": {
    "16": "images/icon_grey16.png",
    "19": "images/icon_grey19.png",
    "24": "images/icon_grey24.png",
    "32": "images/icon_grey32.png",
    "38": "images/icon_grey38.png"
    },
    "default_popup": "action.html",
    "default_title": "Tampermonkey"
    },
    "commands": {
    "open-dashboard": {
    "description": "Open dashboard"
    },
    "open-dashboard-with-running-scripts": {
    "description": "Open dashboard with the current tab's URL used as filter"
    },
    "open-new-script": {
    "description": "Open new script tab"
    },
    "toggle-enable": {
    "description": "Toggle enable state"
    }
    },
    "content_scripts": [ {
    "all_frames": true,
    "js": [ "rea/common.js", "content.js" ],
    "matches": [ "file:///*", "http://*/*", "https://*/*" ],
    "run_at": "document_start"
    } ],
    "content_security_policy": "script-src 'self'; object-src 'self';",
    "default_locale": "en",
    "description": "The world's most popular userscript manager",
    "differential_fingerprint": "1.2ae827c5b75f9e167b3ed0bf65d0c330028dd0acf93a84a8f0f2d7e096024ba3",
    "icons": {
    "128": "images/icon128.png",
    "32": "images/icon.png",
    "48": "images/icon48.png"
    },
    "incognito": "split",
    "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwuYtg7kY2YyNieOkV9pK/qcXwUXu0CFUO0zU6DLAGAJZK7zxrHlwg9a+zFH7CXqgH7zSfRce9KiYOHJaLPBXM66uPCliiQ6Q+bFaNZx1FxLXkZTFnlyPh8kkwwohLJeSQ9NQXqEfeTepDj5BRufAR48az0MC5aUTEj+fFXbzX7QIDAQAB",
    "manifest_version": 2,
    "minimum_chrome_version": "64.0.0.0",
    "name": "Tampermonkey BETA",
    "offline_enabled": true,
    "optional_permissions": [ "downloads" ],
    "options_page": "options.html",
    "options_ui": {
    "chrome_style": false,
    "open_in_tab": true,
    "page": "options.html"
    },
    "permissions": [ "notifications", "unlimitedStorage", "tabs", "idle", "webNavigation", "webRequest", "webRequestBlocking", "storage", "contextMenus", "chrome://favicon/", "clipboardWrite", "cookies", "declarativeContent", "\u003Call_urls>" ],
    "short_name": "TM BETA",
    "update_url": "https://clients2.google.com/service/update2/crx",
    "version": "4.14.6142"
    }
    

    這個是Chrome插件的靈魂, 設置了各種屬性, 包括Chrome插件的圖標, 點擊Chrome插件圖標打開的popup頁面等...
    這里和跨域相關的只有一個: 就是 permissions 屬性.

    這個屬性設置了插件有哪些權限, 比如可以隨意訪問哪些網站.

    比如油猴的, 就有一個 "\u003Call_urls>"permissions 屬性里.
    其中 \u003C 其實就是 < 的Unicode編碼, = <all_urls>, 也就是這個插件定義的JS代碼可以隨意訪問各個網站

    而在用戶眼中就是這幅景象:

    關於Chrome插件配合網站實現跨域的文檔, 可以參考這篇 https://wizardforcel.gitbooks.io/chrome-doc/content/23.html, 總結得很完整了.

    而我搜索的時候, 驚喜的發現, 還有人開發了這樣一個插件(不是我開發的啊):
    名字叫 "Allow CORS", 挺好用的, 初衷是幫助開發者跨域調試網站.

    用戶評價也挺不錯的.
    網址就是 https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf
    用途當然就是和名字一樣, 可以解除跨域限制. 所以你只要讓用戶輕輕一點去裝上這個插件, 就可以無視跨域限制啦!
    不過Chrome因為Google原因, 在國內有限制, 面對一般的用戶Chrome也支持上傳本地包來添加插件, 也很簡單, 下載->一點打開開發者模式->一拖添加插件 就OK啦!

    好了這個方法是真的tql.

  4. 配合客戶端本地代理VPN(終極大招)
    看完第三個方法, 我覺得其他的都要退下了, 畢竟第3個方法應該是最簡單的了.
    第四個原理差不多, 不過開發起來是真的麻煩啊.
    要讓用戶裝一個系統應用, 本地VPN, 就像Charles, Fiddler這樣.
    然后在本地自動修改 Referer 和 Origin 等請求頭, 假裝一個正常的用戶請求.
    總之不是一個優秀的解決方案吧.

  5. 配合后端(終極大招)
    本文着重純前端開發, 我也不太懂后端(基本的php除外, 用來建博客要用到)
    這個方法也是很實用的, 但是不詳細介紹了.
    就是針對不涉及用戶在瀏覽器中cookie的情況, 通過后端語言(如Java)正常請求來獲取資源.
    再返回到前端, 請求一個本站資源(其實轉自對方站).

    比如第一章中提到的音樂播放器, Github上就有人用配合后端實現了! 還有1.9k個star!
    不過這個解析下載音樂因為侵權了, 所以2018年起暫停維護了, 不過下載下來依然可以使用.

    不過只能下載免費音樂, 付費聽的音樂會ErrorHappensQwQ.
    因為只是后端搜索解析一下, 音樂資源依然是來自對方服務器(所以QQ音樂盜鏈保護還是生效, 不能聽啊... 網易就沒事, 畢竟網易一向開放)
    想了解一下的, 可以啪的點進去: https://github.com/maicong/music

  6. JSONP方法
    對於 script 標簽的資源, 瀏覽器是沒有跨域限制的! (對方按照referer/origin屬性不返回數據的情況除外)

    比如網上就有這樣的實現:

    <!-- 原生JS實現 -->
    <script type="text/javascript">
      window.jsonpCallback = function(res) {
        console.log(res);
      };
    </script>
    <script
      src="http://localhost:80/api/jsonp?&cb=jsonpCallback"
      type="text/javascript"
    ></script>
    <!-- JQuery Ajax實現 -->
    <script src="https://cdn.bootcss.com/jquery/3.5.0/jquery.min.js"></script>
    <script>
      $.ajax({
        url: "http://localhost:80/api/jsonp",
        dataType: "jsonp",
        type: "get",
        data: {
          msg: "hello"
        },
        jsonp: "cb",
        success: function(data) {
          console.log(data);
        }
      });
    </script>
    

    嗯, 就是這樣用的, 很簡單獲取Script內容, 不過也只支持Script qwq...

  7. WebSocket實現
    WebSocket是HTML5的一個特性, 可以讓瀏覽器化被動為主動發送內容, 適合實時直播等場景(比如字節的掘金直播就用到了這種方法)

    WebSocket其實雖然有用(本來就沒有CORS的跨域限制), 但其實也沒有辦法獲取HTTP資源QAQ.

    所以這個方法也不推薦吧!

  8. window.postMessage() 方法
    這個方法可以安全地實現跨源通信!

    不了解這個方法, 可以去這里補補課~ ->> https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

    在《HTML5CSS3權威指南》中也有介紹, 但是在實戰中這個方法使用也比較少哈~

    這個方法可以進行不同界面的消息傳遞:
    比如多窗口之間, 網頁和其iframe之間.

    比如QQ音樂就用到了這種方法.
    如果你開啟了多個播放頁面, QQ音樂會通過這個方法多界面之間通信, 自動暫停之前的播放頁, 避免同時播放多個音樂.

    當然正因為它可以 "安全地" 實現跨源通信, 所以這個通信方法也是需要對方服務器認可的. 所以如果要做不正經的事(對方不允許的情況下強行獲取資源)也沒有用啊...

  9. 使用"允許跨域"方法打開瀏覽器
    既然是瀏覽器搞的限制, 能不能關閉這個限制呢?
    是可以的!

    就以這種方法打開(Windows, xxx是你的data目錄):

    C:/.../.../path/chrome.exe --disable-web-security --user-data-dir=xxxx
    

    Mac也可以! 也是一樣的.

    --disable-web-security --user-data-dir=~/Downloads/chrome-data
    

    就是這樣, 不過要重啟Chrome才行, 用戶可能不願意, 所以還是插件這個方法我最推薦.

當然, 如果不正當獲取了第三方內容是可能會有律師函警告的~
所以說, 本文只是對跨域的介紹和技術上的探索與研究, 僅此而已. (你懂的[doge]

->> Details

附錄 - CORS請求與JSONP的比較

CORS與JSONP的使用目的相同, 但是比JSONP更強大.

JSONP只支持GET請求, CORS支持所有類型的HTTP請求. JSONP的優勢在於支持老式瀏覽器, 以及可以向不支持CORS的網站請求數據.

MDN中文文檔 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

MDN 英文文檔 https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

阮一峰 https://www.ruanyifeng.com/blog/2016/04/cors.html

秋風的筆記 https://segmentfault.com/a/1190000022398875

思否 - 安靜de沉淀 https://segmentfault.com/a/1190000011145364

掘金 - 小銘子 https://juejin.cn/post/6844903882083024910

掘金 - JackySummer https://juejin.cn/post/6861553339994374157

Chrome Developers https://developer.chrome.com/docs/extensions/mv3/xhr/

Html5Rocks https://www.html5rocks.com/en/tutorials/cors//

博客園 - 小火柴的藍色理想 https://www.cnblogs.com/xiaohuochai/p/6036475.html

知乎 - 單純前端能否解決跨域問題? https://www.zhihu.com/question/302245173

MDN - XHR介紹 https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest

MDN - XHR介紹(英文) https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest

MDN - Access-Control-Allow-Origin 屬性介紹 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

MDN - Access-Control-Allow-Origin 屬性介紹(英文) https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

StackOverflow - How does Access-Control-Allow-Origin header work? https://stackoverflow.com/questions/10636611/how-does-access-control-allow-origin-header-work

StackOverflow - CORS with XMLHttpRequest not working https://stackoverflow.com/questions/25296455/cors-with-xmlhttprequest-not-working

W3 - CORS Enabled https://www.w3.org/wiki/CORS_Enabled

->> Version History

現在版本為V1.0 (對了博客園的自定義CSS我沒有好好研究, 所以最后渲染結果(UI)可能不盡人意, 所以下一版應該會添加自定義CSS美化一下的!)
詳見 Github(@flightmakers)

2021.8.23 發布V1.0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM