1

我有一个私人 Intranet 风格的网站,每个人都必须先登录才能看到任何内容。一旦他们登录,每个页面都是相同的 - 所以我希望这些页面缓存在 Varnish 中,但仍然需要快速的用户访问检查。

所以我想这样做,我会在我的 VCL 文件中创建一个规则,将每个传入的请求重写到一个文件。该文件不被缓存并检查用户是否有效,如果是,则打印缓存页面的 esi 包含。

这一切都很好,除了将缓存页面的第二个请求标识为经过身份验证。我正在考虑在请求中添加一个查询字符串,并检查它。或者也许有一种方法可以检查是否已通过 esi:include 发出请求。也许我以错误的方式处理这个问题?

有什么建议么?

4

3 回答 3

1

如果您不想在 URL 中使用带有身份验证令牌的经过身份验证的请求,您可以检查 req.esi_level 并确保它对于需要登录的资源大于 0。

if (req.esi_level == 0 && req.url ~ "^/private/.*" ) {
    error (403);
}

需要注意的是,您需要防止从除清漆之外的所有内容访问您的后端——您可能无论如何都在这样做,但值得注意的是。

于 2013-07-17T15:45:37.057 回答
0

如果您只想要基本的身份验证检查,您可以使用http://blog.tenya.me/blog/2011/12/14/varnish-http-authentication/中所述的普通 HTTP 身份验证:

用户:通过

$echo -n "foo:bar" | base64

VCL

sub vcl_fetch {
# ...
  if (! req.http.Authorization ~ "Basic Zm9vOmJhcgo=")
  {
    error 401 "Restricted";
  }
# ...
}

sub vcl_error {
# ...
  if (obj.status == 401) {
    set obj.http.Content-Type = "text/html; charset=utf-8";
    set obj.http.WWW-Authenticate = "Basic realm=Secured";
    synthetic {" 
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
    <HTML>
    <HEAD>
    <TITLE>Error</TITLE>
    <META HTTP-EQUIV='Content-Type' CONTENT='text/html;'>
    </HEAD>
    <BODY><H1>401 Unauthorized (varnish)</H1></BODY>
    </HTML>
    "};
    return (deliver);
  }
# ...
}

如果您更喜欢当前的方法,您总是可以在第一个请求上设置一个 cookie,然后检查 cookie 是否存在。

于 2013-07-16T21:41:09.900 回答
0

这是我在开发环境中尝试过的,我还不确定我们是否会在生产中使用它。

清漆配置

probe checkslash {
    .url = "/robots.txt";
    .interval = 500s;
    .timeout = 10s;
}    

include "backends.vcl";

/** generic config from here down */
sub vcl_recv{

    /* if the drupals are down, this is how long we cache for */
    set req.grace = 6h;

    /* Make sure we direct 443 traffic to the secure drupal */
    if (server.port == 443 ) {
      set req.backend = drpau_ssl_director;

   } else {
      /* port 80 traffic goes to the correct LB */
      set req.backend = drpau_director;
    }
 # just pass through non-page files, and the login page
   if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js|htc|ejs)(\?.*)?$") {
       } else if (req.url ~ "(?i)(sites/default/files)|(js/)|(/login)" ) { 
    } else if (req.esi_level == 0 ) {
     # pass regular pages to a spoecial url
     set req.url = "/esi" + req.url;
   }
    return (lookup);
}



sub vcl_fetch {

 if (req.url ~ "/esi/" && req.esi_level == 0 ) {
       set beresp.do_esi = true; /* Do ESI processing               */ 
    }

}

然后在 apache 中,我重定向所有通过 esi 前缀的页面请求

RewriteRule ^esi/(.*)$ test.php [L]

和测试 php 是

<?php 
define('DRUPAL_ROOT', getcwd());
// We prepare only a minimal bootstrap.
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
global $user;
$roles = user_roles();

if (in_array('anonymous user', $user->roles)) {
  $uri = preg_replace('#^/esi#', '', $_SERVER[REQUEST_URI]);
  echo "<esi:include src=\"http://$_SERVER[SERVER_NAME]$uri\"/>";
} else {
    header("Location: https://$_SERVER[SERVER_NAME]/login");
}
于 2013-10-15T20:01:16.063 回答