Zend framework 使用Zend_Cache_Backend_Static将静态页面缓存为HTML,是否可以限制Zend Framework应用程序的$_GET参数数量
我刚刚使用Zend_Cache_Backend_static设置了静态页面缓存,以便在我的应用程序中为缓存的html文件提供服务,这非常有效。我唯一关心的是它缓存带有$\u GET参数的文件的方式。因为它会自动创建一个映射到提供的URL路由的文件夹结构,所以在大量$\u 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
/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¶m2=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的问题。下面的解决方案解决了这个问题,我们可以通过限制请求中斜杠的数量来减少对路由的限制。