将 cookie 传递给 CloudFront 源但防止缓存 [英] Pass cookie to CloudFront origin but prevent from caching

查看:25
本文介绍了将 cookie 传递给 CloudFront 源但防止缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Symfony Web 应用程序前面使用 CloudFront 作为缓存.为了根据用户角色(管理员、客户等)获取缓存,我在 Lambda@Edge 查看器请求触发器中生成了基于用户角色的哈希.我将该哈希作为请求标头作为 X-User-Context-Hash 传递给我的源.

I am using CloudFront as cache in front of my Symfony web application. To get a cache based on a user's role (admin, customer,...) I generate a user role based hash in a Lambda@Edge Viewer Request trigger. I pass that hash on as a request header to my origin as X-User-Context-Hash.

我的问题是现在我需要将 PHPSESSID cookie 传递到我的源以获得正确的缓存响应,但我不想基于 的值缓存PHPSESSID.我只需要我的缓存响应基于 X-User-Context-Hash 的值而不是我的会话 cookie.

My problem is now that I need to pass the PHPSESSID cookie on to my origin to get the right response for caching, but I do not want to base the cache on the value of PHPSESSID. I do only need my cached response to be based on the value of X-User-Context-Hash but not on my session cookie.

下图应该能详细解释我的问题

The image below should explain my problem in detail

有没有可能做到这一点?

Is there any possibility to accomplish that?

非常感谢您的帮助.

这是我的 Lambda@Edge 查看器请求触发器:

Here's my Lambda@Edge Viewer Request trigger:

'use strict';

function parseCookies(headers) {
    const parsedCookie = {};
    if (headers.cookie) {

        console.log(`${headers.cookie[0].value}`);

        headers.cookie[0].value.split(';').forEach((cookie) => {
            if (cookie) {
                const parts = cookie.split('=');
                parsedCookie[parts[0].trim()] = parts[1].trim();
            }
        });
    }
    return parsedCookie;
}

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

    const https = require('https');

    // Read session cookie
    const parsedCookies = parseCookies(headers);
    let cookie = '';
    if (parsedCookies) {
        if(parsedCookies['PHPSESSID']) {
            cookie = `PHPSESSID=${parsedCookies['PHPSESSID']}`;
        }
    }

    console.log(`Cookie: ${cookie}`);

    // Send request to origin host at /_fos_user_context_hash
    // passing the original session cookie
    const options = {
        hostname: `${request.headers.host[0].value}`,
        port: 443,
        path: '/_fos_user_context_hash',
        method: 'HEAD',
        headers: {
            'Cookie': cookie, 
            'Accept': 'application/vnd.fos.user-context-hash',
            'Vary' : 'Cookie'
        }
    };

    const req = https.request(options, (res) => {
      console.log('statusCode:', res.statusCode);
      console.log('headers:', res.headers);

      // Read the X-User-Context-Hash from the hash endpoint
      const headerName = 'X-User-Context-Hash';
      let hash = 'anonymous';

      if (res.headers[headerName.toLowerCase()]) {
        hash = res.headers[headerName.toLowerCase()];
      }

      // Append X-User-Context-Hash before passing request on to CF
      request.headers[headerName.toLowerCase()] = [{ key: headerName, value: hash }];  

      callback(null, request);

    }).on('error', (e) => {
      console.error(e);
      // Forward request anyway
      callback(null, request);
    });

    req.end();
}


;

推荐答案

以下是我最终解决问题的方法:

Here's how I finally solved my problem:

我将行为配置为不将任何 cookie 转发到源,而是仅根据标头 HostX-User-Context-Hash 进行缓存(参见屏幕截图).

I configured the behavior not to forward any cookies to the origin, but only cache based on the headers Host and X-User-Context-Hash (see screenshot).

下图解释了我的 lambda@edge 过程:

The following image explains my lambda@edge process:

  1. 在查看器请求"触发器中,我读取了名为 PHPSESSIDREMEMBERME 的基于用户的 cookie,并通过 X-Session-Cookies 标题打开.
  2. 如果我的请求 url 与给定的 HostX-User-Context-Hash 标头匹配,则 Cloud-Front 返回缓存的项目并在此处停止.
  3. 如果没有匹配项,则会触发源请求"触发器.当该事件触发时,自定义标头 X-Session-Cookies 可用.因此,我从 X-Session-Cookies 标头中获取值并将 request.headers.cookie 的值设置为该值.此步骤可确保在缓存页面之前将 PHPSESSIDREMEMBERME cookie 都传递给源.
  1. In the "Viewer Request" trigger I read the user-based cookies named PHPSESSID and REMEMBERME and pass those values via the X-Session-Cookies header on.
  2. If the there's a match for my request url and the given Host and X-User-Context-Hash headers, Cloud-Front returns the cached item and stops here.
  3. If there's no match the "Origin Request" trigger is fired. When that event fires the custom header X-Session-Cookies is available. So I take the value from the X-Session-Cookies header and set the value of request.headers.cookie to that value. This step ensures that the PHPSESSID and REMEMBERME cookie are both passed to the origin before the page gets cached.

我的 Lambda@Edge 函数:

查看者请求触发器:

'use strict';

function parseCookies(headers) {
    const parsedCookie = {};
    if (headers.cookie) {

        console.log(`${headers.cookie[0].value}`);

        headers.cookie[0].value.split(';').forEach((cookie) => {
            if (cookie) {
                const parts = cookie.split('=');
                parsedCookie[parts[0].trim()] = parts[1].trim();
            }
        });
    }
    return parsedCookie;
}

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

    const https = require('https');

    let sessionId = '';

    // Read session cookie
    const parsedCookies = parseCookies(headers);
    let cookie = '';
    if (parsedCookies) {
        if(parsedCookies['PHPSESSID']) {
            cookie = `PHPSESSID=${parsedCookies['PHPSESSID']}`;
        }
        if(parsedCookies['REMEMBERME']) {
            if (cookie.length > 0) {
                cookie += ';';
            }
            cookie += `REMEMBERME=${parsedCookies['REMEMBERME']}`;
        }
    }

    console.log(`Cookie: ${cookie}`);

    // Send request to origin host at /_fos_user_context_hash
    // passing the original session cookie
    const options = {
        hostname: `${request.headers.host[0].value}`,
        port: 443,
        path: '/_fos_user_context_hash',
        method: 'HEAD',
        headers: {
            'Cookie': cookie, 
            'Accept': 'application/vnd.fos.user-context-hash',
            'Vary' : 'Cookie'
        }
    };

    const req = https.request(options, (res) => {
      console.log('statusCode:', res.statusCode);
      console.log('headers:', res.headers);

      // Read the X-User-Context-Hash from the hash endpoint
      const headerName = 'X-User-Context-Hash';
      let hash = 'anonymous';

      if (res.headers[headerName.toLowerCase()]) {
        hash = res.headers[headerName.toLowerCase()];
      }

      // Append X-User-Context-Hash before passing request on to CF
      request.headers[headerName.toLowerCase()] = [{ key: headerName, value: hash }];

      const sessionHeaderName = 'X-Session-Cookies';
      request.headers[sessionHeaderName.toLowerCase()] = [{ key: sessionHeaderName, value: cookie }];  

      callback(null, request);

    }).on('error', (e) => {
      console.error(e);
      // Forward request anyway
      callback(null, request);
    });

    req.end();
}


;

源请求触发器:

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

    const sessionHeaderName = 'X-Session-Cookies';

    let cookie = '';
    if (request.headers[sessionHeaderName.toLowerCase()]) {
        console.log(request.headers[sessionHeaderName.toLowerCase()]);
        cookie = request.headers[sessionHeaderName.toLowerCase()][0].value;
    }

    request.headers.cookie = [{ key : 'Cookie', value : cookie }];

    callback(null, request);
};

这篇关于将 cookie 传递给 CloudFront 源但防止缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆