【问题标题】:Varnish response based on Cookie基于 Cookie 的清漆响应
【发布时间】:2020-09-23 19:06:51
【问题描述】:

我有以下 Varnish 配置:


# Default backend definition. Set this to point to your content server.
backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

sub vcl_hash {

    if (req.http.cookie ~ "wordpress_logged_in_[a-z0-9]+") {
        set req.http.X-TMP = regsuball(req.http.cookie, "wordpress_logged_in_[a-z0-9]+=[^;]+(; )?", "; \1=");
        hash_data(req.http.X-TMP);
        unset req.http.X-TMP;
  }

}

sub vcl_recv {

    #Admin Area
    if (req.url ~ "wp-admin|wp-login") {
        return (pass);
    }


    #woocommerce specifics
    if (req.url ~ "^/(cart|my-account|checkout|addons)") {
        return (pass);
    }

    if ( req.url ~ "\?add-to-cart=" ) {
        return (pass);
    }


    set req.http.cookie = regsuball(req.http.cookie, "wp-settings-\d+=[^;]+(; )?", "");
    set req.http.cookie = regsuball(req.http.cookie, "wp-settings-time-\d+=[^;]+(; )?", "");
    set req.http.cookie = regsuball(req.http.cookie, "wordpress_test_cookie=[^;]+(; )?", "");
    #set req.http.cookie = regsuball(req.http.cookie, "wordpress_logged_in_[a-z0-9]+=[^;]+(; )?", "; \1=");

    #more woocommerce specifics

    # Unset Cookies except for WordPress admin and WooCommerce pages
    if (!(req.url ~ "(wp-login|wp-admin|cart|my-account/*|wc-api*|checkout|addons|logout|lost-password|product/*)")) {
        unset req.http.cookie;
    }

    # Pass through the WooCommerce dynamic pages
    if (req.url ~ "^/(cart|my-account/*|checkout|wc-api/*|addons|logout|lost-password|product/*)") {
        return (pass);
    }

    # Pass through the WooCommerce add to cart
    if (req.url ~ "\?add-to-cart=" ) {
        return (pass);
    }

    # Pass through the WooCommerce API
    if (req.url ~ "\?wc-api=" ) {
        return (pass);
    }

    if (req.http.cookie == "") {

        unset req.http.cookie;
    }

    return(hash);
}


sub vcl_backend_response {
    # Happens after we have read the response headers from the backend.
    #
    # Here you clean the response headers, removing silly Set-Cookie headers
    # and other mistakes your backend does.

    if (beresp.ttl == 120s) {

        set beresp.ttl = 1h;

    }

    #set beresp.http.host = bereq.http.host;
}

sub vcl_deliver {
    # Happens when we have all the pieces we need, and are about to send the
    # response to the client.
    #
    # You can do accounting or modifying the final object here.
}

我的目标是确保我在 URL 上有两个不同的缓存版本,具体取决于用户是否登录。我可以通过名为 wordpress_logged_in_[some id] 的 cookie 来确定。

我试图在this article 中找到这方面的灵感,但我无法根据客户端是否有前面提到的 cookie 得到两种不同的结果。对我来说,无论 cookie 是否存在,它似乎都是相同的缓存内容。

如果能帮助我理解我的问题,我将不胜感激。

【问题讨论】:

    标签: varnish varnish-vcl varnish-4


    【解决方案1】:

    应用文章中建议的解决方案将产生与登录用户一样多的缓存条目(每用户缓存)。

    如果您希望一个缓存对象用于访客,另一个缓存对象用于所有登录用户,则在基于 cookie 的存在设置的“布尔值”上进行散列:

    sub vcl_hash {
      if (req.http.cookie ~ "wordpress_logged_in_") {
        hash_data("wordpress_logged_in");
      }
      # the builtin.vcl will take care of also varying cache on Host/IP and URL 
    }
    

    只有在存在 cookie 时生成的页面不包含特定于用户的内容,这才是安全的。例如,如果“登录页面”与“注销页面”的区别仅在于网站标题部分中存在“注销”文本。

    任何地方的内容都是用户特定的,你不想应用这样的逻辑。例如,标题文本中的“Hi, John”。

    【讨论】:

    • 嗨。感谢你的回复。我尝试了您的建议,并按照here 的建议检查了生成的哈希值。无论cookie是否存在,似乎都没有添加哈希数据。
    • 可能你忘记重新加载配置了?根据输出的第三行,它仍然在 cookie 上进行散列,而不是在 cookie 存在值(“wordpress_logged_in”)上。这是第一个请求。对于其他请求,这是正常的,因为您为非管理员 URL 调用 unset req.http.cookie,所以 vcl_hash(稍后调用)没有 cookie 可玩。
    • 如果我删除了。 unset req.http.cookie,我不会只是在缓存多个不同版本时遇到问题吗?
    • 是的。我指的是测试 URL。仅当 wordpress_logged_in_<id> 存在或不存在时,您似乎才希望具有答案中指定的逻辑。所以只测试它真正变化的地方。 /wp-content/plugins/... 之类的 URL 不关心 cookie,因此不会为它设置 cookie(您正在剥离它)。因此,请确保您只测试相关的 URL,其中 cookie 未被剥离,例如/wp-admin/foo 在此之前,重新加载配置以应用新逻辑。
    【解决方案2】:

    看起来您所做的一切都是正确的,但我建议您进行一些调试。

    如果你运行以下命令,Hash标签会出现在varnishlog中:

    varnishadm param.set vsl_mask +hash
    

    然后您可以运行以下命令以根据 cookie 检查哈希是否不同

    varnishlog -g request -i requrl -i hash -I reqHeader:Cookie
    

    此日志记录命令列出以下项目:

    • 请求网址
    • cookie 标头
    • 创建的哈希

    这应该可以帮助您弄清楚发生了什么。

    【讨论】:

    • 感谢您的回答。我按照建议添加了哈希标记,并为设置了 Cookie 的客户端添加了输出的 here's the output。哈希似乎不包含与没有 cookie 的客户端的差异。
    • 您的输出显示/wp-admin/admin-ajax.php 的散列确实包含cookie 值,而/webshop/global-100-bf-triple-black-smooth-g31-2/ 的散列不包含。所以这行得通。但是,regsuball() 中的正则表达式似乎没有捕捉到正确的值。但我想知道这个正则表达式问题是否相关,因为您的输出显示基于 cookie 的不同哈希值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-09
    • 2014-03-14
    • 2012-08-19
    • 2013-06-22
    • 2023-02-10
    • 2016-02-02
    • 1970-01-01
    相关资源
    最近更新 更多