1. 程式人生 > 實用技巧 >前端計網部分學習總結

前端計網部分學習總結

跨域問題

什麼是跨域

什麼是同源策略

同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSRF等攻擊。所謂同源是指"協議+域名+埠"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。

同源策略限制的內容
  • Cookie、LocalStorage、IndexedDB等儲存性內容
  • DOM節點
  • AJAX請求傳送後,結果被瀏覽器攔截了

但是有三個標籤是允許跨域載入資源的

  • <img src=XXX>
  • <link href=XXX>
  • <script src=XXX>

常見的跨域場景

協議、子域名、主域名、埠號

任意一個不相同時,都算作不同域。不同域之間請求資源就算作“跨域”。

注:跨域請求並不是請求發不出去,請求是可以傳送的,服務端也可以收到請求並正常返回,但由於瀏覽器的同源策略,響應結果被攔截了

跨域解決方案

JSONP

  1. JSONP的原理:

    利用 <script> 標籤沒有跨域限制的漏洞,網頁可以得到從其他來源動態產生的 JSON 資料。JSONP請求一定需要對方的伺服器做支援才可以。

  2. JSONP的實現流程:

    比如,有個a.html頁面,它裡面的程式碼需要利用ajax獲取一個不同域上的json資料,假設這個json資料地址是http://damonare.cn/data.php,那麼a.html中的程式碼就可以這樣:

    <script type="text/javascript">
        function dosomething(jsondata){
            //處理獲得的json資料
        }
    </script>
    <script src="http://example.com/data.php?callback=dosomething"></script>
    

    我們看到獲取資料的地址後面還有一個callback引數,按慣例是用這個引數名,但是你用其他的也一樣。當然如果獲取資料的jsonp地址頁面不是你自己能控制的,就得按照提供資料的那一方的規定格式來操作了。

    因為是當做一個js檔案來引入的,所以http://damonare.cn/data.php返回的必須是一個能執行的js檔案,所以這個頁面的php程式碼可能是這樣的(一定要和後端約定好哦):

    <?php
    $callback = $_GET['callback'];//得到回撥函式名
    $data = array('a','b','c');//要返回的資料
    echo $callback.'('.json_encode($data).')';//輸出
    ?>
    

    最終,輸出結果為:dosomething(['a','b','c']);

    如果你的頁面使用jquery,那麼通過它封裝的方法就能很方便的來進行jsonp操作了。

    <script type="text/javascript">
        $.getJSON('http://example.com/data.php?callback=?,function(jsondata)'){
            //處理獲得的json資料
        });
    </script>
    

    jquery會自動生成一個全域性函式來替換callback=?中的問號,之後獲取到資料後又會自動銷燬,實際上就是起一個臨時代理函式的作用。$.getJSON方法會自動判斷是否跨域,不跨域的話,就呼叫普通的ajax方法;跨域的話,則會以非同步載入js檔案的形式來呼叫jsonp的回撥函式。

  3. JSONP的優缺點

    • JSONP的優點是:它不像XMLHttpRequest物件實現的Ajax請求那樣受到同源策略的限制;它的相容性更好,在更加古老的瀏覽器中都可以執行,不需要XMLHttpRequest或ActiveX的支援;並且在請求完畢後可以通過呼叫callback的方式回傳結果。

    • JSONP的缺點則是:它只支援GET請求而不支援POST等其它型別的HTTP請求;它只支援跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript呼叫的問題。

CORS跨域

  1. CORS原理

    CORS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與伺服器應該如何溝通。CORS背後的基本思想就是使用自定義的HTTP頭部讓瀏覽器與伺服器進行溝通,從而決定請求或響應是應該成功還是失敗。

    瀏覽器的請求頭重會含有origin的頭資訊,用來表明請求的來源。而伺服器一個響應頭資訊Access-Control-Allow-Origin,如果這兩個頭的內容匹配,則可以實現跨域。

  2. 兩種請求

    1. 簡單請求

      只要同時滿足以下兩大條件,就屬於簡單請求

      條件1:使用下列方法之一:

      • GET
      • HEAD
      • POST

      條件2:Content-Type 的值僅限於下列三者之一:

      • text/plain
      • multipart/form-data
      • application/x-www-form-urlencoded

      請求中的任意 XMLHttpRequestUpload 物件均沒有註冊任何事件監聽器; XMLHttpRequestUpload 物件可以使用 XMLHttpRequest.upload 屬性訪問。

    2. 複雜請求

      複雜請求是對伺服器有特殊要求的請求,比如請求方法是PUTDELETE,或者Content-Type的欄位型別是application/json

      複雜請求的CORS請求,會在正式通訊之前,增加一次HTTP查詢請求,稱為"預檢"請求,該請求是 OPTION 方法的,通過該請求來知道服務端是否允許跨域請求。

      預檢請求的HTTP頭資訊:

      OPTIONS /cors HTTP/1.1
      Origin: http://api.bob.com
      Access-Control-Request-Method: PUT  /瀏覽器CORS請求用到的HTTP方法
      Access-Control-Request-Headers: X-Custom-Header    /CORS額外發送的透資訊欄位
      Host: api.alice.com
      Accept-Language: en-US
      Connection: keep-alive
      User-Agent: Mozilla/5.0...
      

      服務端收到預檢請求以後,檢查完資訊允許跨源請求,作出迴應。

      TTP/1.1 200 OK
      Date: Mon, 01 Dec 2008 01:15:39 GMT
      Server: Apache/2.0.61 (Unix)
      Access-Control-Allow-Origin: http://api.bob.com  //表示該介面可以請求
      Access-Control-Allow-Methods: GET, POST, PUT  //返回支援的跨域請求方法
      Access-Control-Allow-Headers: X-Custom-Header  //支援所有頭資訊欄位,不限於瀏覽器“預檢”中請求的欄位
      Content-Type: text/html; charset=utf-8
      Content-Encoding: gzip
      Content-Length: 0
      Keep-Alive: timeout=2, max=100
      Connection: Keep-Alive
      Content-Type: text/plain
      

Nginx反向代理

使用nginx反向代理實現跨域,是最簡單的跨域方式。只需要修改nginx的配置即可解決跨域問題,支援所有瀏覽器,支援session,不需要修改任何程式碼,並且不會影響伺服器效能。

實現思路:通過nginx配置一個代理伺服器(域名與domain1相同,埠不同)做跳板機,反向代理訪問domain2介面,並且可以順便修改cookie中domain資訊,方便當前域cookie寫入,實現跨域登入。

先下載nginx,然後將nginx目錄下的nginx.conf修改如下:

// proxy伺服器
server {
    listen       81;
    server_name  www.domain1.com;
    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie裡域名
        index  index.html index.htm;

        # 當用webpack-dev-server等中介軟體代理介面訪問nignx時,此時無瀏覽器參與,故沒有同源限制,下面的跨域配置可不啟用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #當前端只跨域不帶cookie時,可為*
        add_header Access-Control-Allow-Credentials true;
    }
}
複製程式碼

最後通過命令列nginx -s reload啟動nginx

// index.html
var xhr = new XMLHttpRequest();
// 前端開關:瀏覽器是否讀寫cookie
xhr.withCredentials = true;
// 訪問nginx中的代理伺服器
xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
xhr.send();
複製程式碼
// server.js
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request', function(req, res) {
    var params = qs.parse(req.url.substring(2));
    // 向前臺寫cookie
    res.writeHead(200, {
        'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:指令碼無法讀取
    });
    res.write(JSON.stringify(params));
    res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');

搬運文章

前端跨域整理

跨域資源共享CORS詳解

九種跨域方式實現原理

什麼是CDN,CDN回源是什麼

什麼是CDN

CDN(Content Delivery Network)即內容分發網路。通過網路各處放置節點伺服器,CDN可以實時的根據網路流量和各節點的連線、負載狀況以及與使用者的距離等情況將使用者的請求導向離使用者最近的服務節點上。

CDN訪問流程

  1. 當用戶點選URL後,經過本地DNS伺服器的解析,DNS伺服器會最終將域名的解析權交給CNAME裡指向的CDN專用的DNS解析伺服器。
  2. CDN的DNS伺服器將CDN的全域性負載均衡裝置IP地址返回給使用者
  3. 使用者向CDN的全域性負載均衡裝置發出請求
  4. CDN的全域性負載均衡裝置根據使用者的IP地址以及內容請求的URL,選擇一臺使用者所屬的區域負載均衡裝置,告訴使用者向這臺裝置發出請求
  5. 區域負載均衡裝置會為使用者選擇一臺合適的快取伺服器提供服務。根據使用者的IP地址,判斷哪一臺伺服器距離使用者最近,根據使用者請求的URL中攜帶的內容判斷哪一臺伺服器有使用者所需內容,查詢伺服器當前負載情況,判斷哪一臺伺服器尚有服務能力。根據以上條件分析之後,區域負載均衡裝置將快取伺服器的IP地址返回
  6. 使用者向快取伺服器發出請求,快取伺服器響應使用者請求。如果這臺伺服器沒有使用者想要的內容,那麼這臺伺服器會向上一級請求內容,直至追溯到網站的源伺服器將內容拉到本地。

那麼回源是什麼意思

當 CDN 快取伺服器中沒有符合客戶端要求的資源的時候,快取伺服器會請求上一級快取伺服器,以此類推,直到獲取到。最後如果還是沒有,就會回到我們自己的伺服器去獲取資源。 那都有哪些時候會回源呢?沒有資源,資源過期,訪問的資源是不快取資源等都會導致回源。

搬運文章

關於CDN、回源問題一網打盡

CDN知識詳解