symfony - 将cookie传递给CloudFront来源,但阻止缓存

标签 symfony amazon-web-services aws-lambda amazon-cloudfront foshttpcachebundle

我将CloudFront用作Symfony Web应用程序前面的缓存。为了获得基于用户角色(管理员,客户等)的缓存,我在Lambda @ Edge Viewer Request触发器中生成了基于用户角色的哈希。我将该哈希作为请求 header 传递给X-User-Context-Hash到我的来源。

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

下图应详细说明我的问题

有可能做到这一点吗?

将不胜感激。

enter image description here

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

'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();
}


;

最佳答案

这是我终于解决我的问题的方法:

CloudFront行为

我将行为配置为不将任何cookie转发到源,而是仅基于头HostX-User-Context-Hash缓存(请参见屏幕截图)。

Screenshot CloudFront behavior

下图说明了我的lambda @ edge流程:
lambda@edge process

  • 在“查看器请求”触发器中,我读取了名为PHPSESSIDREMEMBERME的基于用户的cookie,并通过X-Session-Cookies header 传递了这些值。
  • 如果我的请求网址与给定的HostX-User-Context-Hash header 匹配,则Cloud-Front返回缓存的项目并在此处停止。
  • 如果不匹配,则触发“Origin Request”触发器。当该事件触发时,自定义 header X-Session-Cookies可用。因此,我从X-Session-Cookies header 中获取值,并将request.headers.cookie的值设置为该值。此步骤可确保在缓存页面之前,将PHPSESSIDREMEMBERME Cookie都传递到源。

  • 我的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);
    };
    

    关于symfony - 将cookie传递给CloudFront来源,但阻止缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47569633/

    相关文章:

    Symfony 2 获取登录用户列表

    php - Symfony3 : Centralized exception handling

    amazon-web-services - 超时后无法部署到 AWS Elastic Beanstalk

    amazon-web-services - Cloudformation 无法解析参数 - VolumeAttachment

    amazon-web-services - 从 AWS Lambda 调用时,AWS DynamoDB 返回验证错误

    php - 识别 Twig 变量中的空白

    php - 如何获取 Symfony 控制台应用程序的运行路径?

    python - 如何在不编写代码的情况下在 amazon sqs 中实现指数退避

    security - API 网关的可选授权

    node.js - AWS Lambda - 错误 : unable to get local issuer certificate