Zend framework 使用Zend_Cache_Backend_Static将静态页面缓存为HTML,是否可以限制Zend Framework应用程序的$_GET参数数量

Zend framework 使用Zend_Cache_Backend_Static将静态页面缓存为HTML,是否可以限制Zend Framework应用程序的$_GET参数数量,zend-framework,mod-rewrite,zend-cache,Zend Framework,Mod Rewrite,Zend Cache,我刚刚使用Zend_Cache_Backend_static设置了静态页面缓存,以便在我的应用程序中为缓存的html文件提供服务,这非常有效。我唯一关心的是它缓存带有$\u GET参数的文件的方式。因为它会自动创建一个映射到提供的URL路由的文件夹结构,所以在大量$\u GET参数可能被故意附加到现有页面的情况下,这是否存在潜在的安全风险?达到最大目录深度或最大文件长度 例如:目前我正在将页面缓存到/public/cache/static/中,因此使用标准路由器/module/controlle

我刚刚使用Zend_Cache_Backend_static设置了静态页面缓存,以便在我的应用程序中为缓存的html文件提供服务,这非常有效。我唯一关心的是它缓存带有$\u GET参数的文件的方式。因为它会自动创建一个映射到提供的URL路由的文件夹结构,所以在大量$\u GET参数可能被故意附加到现有页面的情况下,这是否存在潜在的安全风险?达到最大目录深度或最大文件长度

例如:目前我正在将页面缓存到
/public/cache/static/
中,因此使用标准路由器
/module/controller/action/param1/val1/param2/val2
或标准查询字符串
/module/controller/action?param1=val1¶m2=val2
将创建以下目录结构:

/public/cache/static/module/controller/action/param1/val1/param2/val2.html 
/public/cache/static/module/controller/action?param1=val1&param2=val2.html
允许人们以这种方式(无论多么有限)创建目录结构让我有点担心。Zend_Cache_Backend_Static和相应的Zend_Cache_Frontend_Capture都必须在ini文件中设置,而不是通过Zend_Cache factory,并且似乎没有任何设置选项

这可能只是用限制$GET变量数量的自定义路由替换默认路由器的情况吗?这是可能的,还是我需要精确地指定每条路线所需的变量(不是世界末日,而是更具限制性的变量)

更新:

因此,处理静态缓存的现有重写规则如下所示:

RewriteCond %{REQUEST_METHOD} GET
RewriteCond %{DOCUMENT_ROOT}/cached/index.html -f
RewriteRule ^/*$ cached/index.html [L]

RewriteCond %{REQUEST_METHOD} GET
RewriteCond %{DOCUMENT_ROOT}/cached/%{REQUEST_URI}\.html -f
RewriteRule .* cached/%{REQUEST_URI}\.html [L]

RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]

RewriteRule ^.*$ index.php [NC,L]
如果请求命中静态缓存中的页面,它将发送该html页面。如果没有,它将点击Zend框架并生成它

我可以在开头添加以下内容:

RewriteCond %{QUERY_STRING} \S
RewriteRule [^\?]+ /$0? [R=301,L]

这将彻底删除我的查询字符串。这很好,因为我仍然可以使用Zend Framework的URL路径方法传递$\u GET变量(我还通过提供非常明确的路由来限制该方法)。但是不重定向就可以做到这一点吗?

理想的方法是将其定义为一个RewriteCond,但我不确定是否可以使用mod_rewrite来计算GET参数的数量

因此,最好的解决方案可能是重定向到一个独立的php脚本,该脚本决定是否使用缓存的html文件

<?php

if (count($_GET) >= 20) {
  require __DIR__ . 'index.php';
} else {
  require '/path/to/cache.html';
}

确定,因此删除查询字符串的重写规则将在没有重定向的情况下工作

问题(我怀疑)是Zend_Cache_Backend_Static正在使用$_SERVER['REQUEST_URI']来访问原始文件名。我对mod_rewrite的了解非常有限,我没有意识到这个值没有改变

因此,为了防止大量查询字符串创建文件和目录,我必须执行以下操作:

首先,对于标准查询字符串:

在我的mod_重写开始时剥离查询字符串,而不重定向:

RewriteCond %{QUERY_STRING} \S
RewriteRule [^\?]+ /$0?
然后,在我的index.php中,我将通过剥离查询字符串来更改$_服务器['REQUEST_URI'],以匹配重定向,这意味着我不再需要破解ZF:

$queryIndex = strpos($_SERVER['REQUEST_URI'], '?');
if($queryIndex !== false) {
    $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], 0, $queryIndex);
}
这将阻止我的应用程序解释任何查询字符串。因此,为了将变量传递给页面,我使用了Zend Framework url路径参数。为了防止它们创建过深的缓存文件夹,我在引导中用几个非常明确定义的路由替换了默认路由:

$frontController = Zend_Controller_Front::getInstance(); 
$router = $frontController->getRouter();

$route = new Zend_Controller_Router_Route(
    ':module/:controller/:action',
    array(
        'module' => 'default',
        'controller' => 'index',
        'action' => 'index'
    )
);

$router->addRoute('default', $route);

$route = new Zend_Controller_Router_Route(
    'article/:alias',
    array(
        'module' => 'default',
        'controller' => 'article',
        'action' => 'index',
        'alias' => ''
    )
);

$router->addRoute('article', $route);
在这里,我替换了默认路由,因此不允许使用其他参数。因此,任何需要参数的操作都必须显式设置,例如在我的第二条路线中。这意味着可能存在许多已定义的路由。谢天谢地,在我的特殊应用程序中,情况并非如此

限制路由如此之多并允许通过ZF URL路径使用某些GET参数的一种方法是限制请求URI中的斜杠数,从而有效地限制静态页面缓存的最大目录深度(下面的10)。这也可以在index.php中更改:

if(substr_count($_SERVER['REQUEST_URI'], '/') > 10) {
    preg_match_all("/\//", $_SERVER['REQUEST_URI'] ,$capture, PREG_OFFSET_CAPTURE);
    $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], 0, $capture[0][9][1]);
}

Zend_Cache_Backend_Static的想法是,如果缓存文件可用,则完全绕过PHP和Zend Framework MVC堆栈。它通过使用mod_rewrite重定向到现有html页面来实现这一点。我在上面的问题中添加了更多的细节。对,我理解。。但我想说的是,由于mod_重写的局限性,我认为这是不可能的。但是无论哪种方式,运行上面的脚本来决定是否使用缓存都要比加载整个MVC堆栈便宜得多。没错,但是我们希望通过CDN或反向代理nginx避免PHP和Apache在html缓存命中上出现冲突。我很高兴完全删除查询字符串并处理url路径变量,我只是不想显式地定义每个路由。在这种情况下,您可以添加一个
usecache=true
GET
param,并使用类似这样的
RewriteCond%{query_string}([^&]&)*usecache(&|$)来观察它
。。。但是我不知道如何避免Apache。上面的mod_重写已经处理了这个缓存。如果一个ZF格式的URL命中一个现有的缓存文件,那么这将被提供,如果它没有命中PHP。当提供缓存文件时,我们可以在80以外的端口上运行Apache,使用类似nginx on 80的东西,如果存在缓存文件,则提供缓存文件,如果没有,则转发给Apache。这是一个反向代理,基本上是我们自己的CDN。我们真正担心的是GET params的问题。下面的解决方案解决了这个问题,我们可以通过限制请求中斜杠的数量来减少对路由的限制。