2017-08-29 21 views
1

我想在發送到源服務器之前刪除aws雲中的特定cookie。 我必須將所有的cookie發送到起始地址,除了名爲"_x_ad_zone"的cookie。AWS Cloudfront在發送到源之前刪除特定的Cookie

我找不到任何選項來刪除雲端配置中的特定cookie。我相信我們必須用lambda來實現,但我不知道如何去做。

請讓我知道我該如何做到這一點。

[編輯] 基於這個答案,我寫了下面的lambda @ edge來解決我的問題。

exports.handler = (event, context, callback) => { 
    const request = event.Records[0].cf.request; 
    const headers = request.headers; 

    const cookieName = '__a_x_id'; 

    /* 
    * Lambda at the Edge headers are array objects. 
    * 
    * Client may send multiple Cookie headers, i.e.: 
    * > GET /viewerRes/test HTTP/1.1 
    * > User-Agent: curl/7.18.1 (x86_64-unknown-linux-gnu) libcurl/7.18.1 OpenSSL/1.0.1u zlib/1.2.3 
    * > Cookie: First=1; Second=2 
    * > Cookie: ClientCode=abc 
    * > Host: example.com 
    * 
    * You can access the first Cookie header at headers["cookie"][0].value 
    * and the second at headers["cookie"][1].value. 
    * 
    * Header values are not parsed. In the example above, 
    * headers["cookie"][0].value is equal to "First=1; Second=2" 
    */ 
    console.log(headers.cookie); 
    // Delete the cookie if found 
    if (headers.cookie) { 
     for (let i = 0; i < headers.cookie.length; i++) { 
      console.log(headers.cookie[i].value); 
      if (headers.cookie[i].value.indexOf(cookieName) >= 0) { 
       console.log('Adblocker cookie found and delete: '+headers.cookie[i].value); 
       headers.cookie[i].value = "0"; 
       break; 
      } 
     } 
     request.headers = headers; 
    } 

    callback(null, request); 
}; 
+0

您是否確實需要將**所有其他Cookie發送至原始地址?如果這是真的,你會得到很少的緩存命中。最好只發送特定的cookie(或者根本沒有cookie)。如果這真的是你需要的,請幫助我們理解這個cookie需要被刪除的原因,以便我們能夠提出最正確的解決方案。 –

+0

Hi @ Michael-sqlbot我們不需要在CloudFront上緩存任何內容,我們的用例是使用CloudFront作爲代理網關。 –

+0

爲了讓它跳躍而獲得讚譽......但是解決方案存在問題 - 它可能看起來有效,但操作標題時很重要;你寫的東西有一個隱藏的bug,因爲它可以隨意刪除* other * cookies,它實際上是生成一個無效的cookie頭,而不是乾淨地刪除你想阻止的那個。我開發了一個解決方案,在我能夠徹底測試它的預期和意外行爲後,我會提供這個解決方案。 –

回答

1

快速免責聲明:當cookie被轉發到原始服務器時,CloudFront不僅緩存對URI和標題(以及查詢字符串,如果配置爲這樣做)的響應,還針對cookie的唯一組合由瀏覽器提供的值(或缺失的cookie) - 所以只有在緩存中包含(或缺少)完全相同的Cookie和值組合時才能從緩存中提供響應。這對您的緩存命中率沒有好處,但當然,它也是CloudFront的完全正確設計 - 如果提供了不同的Cookie,則CloudFront將無法選擇,只能認爲該Cookie可能會修改返回的響應從原點開始,所以Cookie必須成爲緩存鍵的組成部分。

它你必須轉發cookie,最好轉發特定的cookie。

然而,CloudFront的有一些是無關的緩存應用程序,所以有可能是有效的用例這樣的解決方案。


您的解決方案只會通過簡單和樂觀的測試。有很多邊緣情況下它不能正確處理。對於cookie的操作示例腳本只是一個簡單的例子,包括放棄的大意的東西:

* Header values are not parsed. 

的第一個問題是,瀏覽器是免費的多個餅乾在一個Cookie:頭結合,並且您對headers.cookie[i].value.indexOf(cookieName)的測試不僅會與包含所需cookie的標頭相匹配,還會與包含該cookie的標頭以及其他 ...匹配,並刪除該特定標頭條目中的所有Cookie。

如果在查看器請求觸發器中使用,則使用此解決方案刪除太多Cookie的風險很大。在原始請求觸發器中,它甚至更高,因爲Cookie已被匹配的緩存行爲的cookie轉發配置剝離並重新規範化,並且CloudFront 確實在一個標題行上組合了多個Cookie,至少在某些條件。

的第二個問題是有關第一:indexOf()簡單的字符串匹配將匹配cookie值,以及cookie名稱,因此有可能得到一個cookie 錯誤匹配 - 這你不我想要檢查。

第三個問題是您沒有真正生成有效的重置值。 CloudFront似乎現在接受這一觀點,但由於技術上無效,未來有可能「固定」這種可能性。

我寫了一個Lambda @ Edge腳本,我相信它完全可以處理cookie語義,並且只會刪除您想要刪除的cookie,並且保持數據結構的清潔。因爲我認爲這是一個有趣的用例,所以我寫了它,以便它可以匹配儘可能多的Cookie,而不僅僅是一個cookie,只有cookie名稱上帶有精確字符串,區分大小寫的匹配項。

餅乾配置在靠近頂部的數組中。

在你的情況,有一個名爲__a_x_id是這樣的cookie:

const discard = [ '__a_x_id' ]; 

添加多個cookie名稱的陣列將阻止他們。

這使用Node.js 6.10並與查看器請求觸發器或原始請求觸發器配合使用。如果您正在進行任何緩存,您可能需要將其用作原始請求觸發器,因爲這意味着它觸發的次數較少。

我也很高興地告訴大家,儘管看起來有點複雜,並且做了相當數量的字符串分割並且有多個嵌套循環,但是這個代碼在溫度容器中的Lambda執行時間始終小於1毫秒,是否有任何餅乾被匹配和刪除。

'use strict'; 

// source: https://stackoverflow.com/a/45970883/1695906 

// iterate through all Cookie: headers in a request trigger, 
// removing any cookies on the "discard" list, while preserving 
// the integrity of any other cookies, including those appearing on the same 
// header line, and confirm the resulting "cookie" array to CloudFront 
// requirements by removing any now-empty elements, or the entire array 
// if no cookies remain 

// configure with one or more cookies to be removed from all requests; 
// cookie names are case-sensitive 

const discard = [ 'grover', 'big_bird' ]; // friends of cookie monster 

exports.handler = (event, context, callback) => { 
    const request = event.Records[0].cf.request; 
    const headers = request.headers; 

    // does the request have any cookies? skip to the end, if not 
    if(headers.cookie) 
    { 
     const cookies = headers.cookie; 

     // iterate each Cookie: header, from last to first; 
     // last-to-first makes it simple to splice-out an array element 
     // because we then need not keep track of the reduced array length 

     for (var n = cookies.length; n--;) 
     { 
      // there may be multiple cookies per header line; examine them all 

      const cval = cookies[n].value.split(/;\ /); 
      const vlen = cval.length; // how many we started with 

      // check individual cookies on this line, backwards 
      for (var m = vlen; m--;) 
      { 
       // cookie name is to the left of "=" 
       const cookie_kv = cval[m].split('=')[0]; 
       // run though each member of "discard" array, 
       // removing the cookie if it's a match, 
       // again last to first but for no particular reason, here 
       for(var di = discard.length; di--;) 
       { 
        if(cookie_kv == discard[di]) 
        { 
         cval.splice(m,1); // cookie removed! 
         break; // no need to check any other matches, already gone 
        } 
       } 
      } // for m 

      // if our array of cookies for this header line has now changed in size, 
      // we must have deleted some or all of it, so we need to reassemble 
      // what remains, or eliminate the entire line 

      if(cval.length != vlen) 
      { 
       if(cval.length === 0) // did we remove everything? 
       { 
        // yes? we can eliminate this entire line 
        cookies.splice(n,1); 
       } 
       else 
       { 
        // no? reassemble the remaining cookies 
        headers.cookie[n].value = cval.join('; '); 
       } 
      } 
     } // for n 

     // if the only cookies present in the request were cookies we removed, 
     // we now have a completely empty array in headers.cookie, which 
     // CloudFront should consider invalid; clean it up 
     if(cookies.length === 0) 
     { 
      delete headers.cookie; 
     } 
    } 

    // return control to CloudFront, possibly with our modified request 
    return callback(null, request); 

}; 
0

爲此,您需要編寫一個[email protected]函數來有條件地過濾CloudFront中的cookie。

檢查this例如,瞭解所需操作。另請注意,您需要使用Lambda @ Edge在原始請求事件中更改請求標頭。

相關問題