站点安全正则表达式处理程序? (PHP) [关闭]
Posted
技术标签:
【中文标题】站点安全正则表达式处理程序? (PHP) [关闭]【英文标题】:Site security regex handler? (PHP) [closed] 【发布时间】:2012-09-14 11:01:49 【问题描述】:我工作的一家公司要求我将他们的一个网站设为另一个网站的子域。然后,他们要求我将“登录/注销”会话控制从他们的主域扩展到他们的子域。
完成此操作后,我发现存在控制/管理问题。由于它们有大量的单独页面,并且由于它们广泛的目录结构,它们太复杂了,无法在每个页面中添加 php sn-p 以根据登录状态进行重定向。
这是我的解决方案。如果有任何问题或任何其他对我有帮助的事情,请告诉我。
-
我将使用 Mod_rewrite 将 subdomin 上的每个请求重定向到特定页面 (handler.php?requested_url=)。
我将在他们的网站上创建一个“网站允许/禁止规则”部分。本节将包含一个带有如下规则的文本框:
+/weather/ ---> will allow anyone access to any url that contains "/weather/" somewhere within it, irregardless of logged-in status.
-/weather/premium/ ---> will only allow access to a url that contains /weather/premium to logged-in users.
这将输出到一个存储在 rules.php 文件中的数组,该文件如下所示:
$ruleList = array();
$ruleList[] = '+/weather/';
$ruleList[] = '-/weather/premium/';
在 handler.php 中,如果用户已登录,我会将他们转发到 requested.url。如果用户未登录,那么我将首先假设每个页面都仅限于未登录用户。 handler.php 将解析 requested_url 并对照 rules.php 检查它,看看是否有任何明确的权限设置。然后如果规则允许非登录访问,它会将用户转发到requested_url,否则将其发送到登录页面。
我可以立即看到的一个问题是,鉴于 Mod_rewrite
规则会将每个请求发送到 handler.php,我该如何避免无限循环?
是否应该通过header("Location: ")
以外的其他方法进行重定向?
编辑:这是我的斗争的更新:
在我添加的***域 (example.com) 的 .htaccess 文件中:
#Prevent catching requests for the sub1 subdomain
RewriteCond %REQUEST_URI ^sub1\.example\.com
RewriteRule .* – [L]
然后,在 sub1.example.com 子域的 .htaccess 中,我添加了以下内容:
IndexIgnore *
RewriteEngine On
RewriteBase /path/to/base
#Avoid infinite loop on outgoing requests
RewriteCond %HTTP_REFERER !^$
RewriteCond %REQUEST_URI !^$
RewriteCond %HTTP_REFERER !^/?handler.php?$
RewriteCond %REQUEST_URI !^/?handler.php?$
#Check for cookie. Redirect to handler if not found. (not yet implemented)
#RewriteCond %HTTP_COOKIE !session_id
RewriteRule (.*)$ handler.php?requested_url=$1 [NC,L,QSA]
这里是 handler.php
<?php
$url = $_REQUEST['requested_url'];
//Check list of permissions. For now just assume permitted.
$permitted = true;
if ($url == "") $url = "http://sub1.example.com";
if ($permitted)
header("Location: ".$url);
header("Location: http://sub1.example.com");
?>
我是如此接近,我可以品尝它。不幸的是,目前我几乎在所有地方都得到了“重定向循环”。如果有人可以在正确的方向上推动我,我将不胜感激!
【问题讨论】:
也可以查看ibm.com/developerworks/opensource/library/os-php-secure-apps/… 至于“每页加一个sn-p太累”,你考虑auto_prepend_file吗? 好吧,据我了解您的设置,如果登录页面被归类为受限访问,您应该只获得无限重定向循环,对吗?那么也许你的规则和 URL 解析部分做了一些意想不到的事情? 你可以用这个处理程序尝试一些棘手的反向代理。 【参考方案1】:我认为您的想法中存在循环,因此应用程序中存在循环。像这样:
用户代理请求子域中的旧资源。
由于 UA 必须具有有效凭据,并且旧资源无法验证凭据,因此 UA 被重定向到处理程序。
处理程序验证凭据,并将 UA 重定向回旧资源。
转到 2。
问题是请求的资源无法区分步骤 1 和步骤 3 中的 UA 请求,因为区别是由 UA 的凭据定义的,旧资源不评估该凭据。
从另一个角度来看,这种矛盾也很明显。想象一下,您解决了循环,并且 UA 被重定向到旧资源——类似于http://sub1.example.com/foo.php。对于服务器返回资源,它必须意味着没有评估凭据(因为它不这样做),因此资源实际上是公共的。
要解决这个问题,您必须通过更改第 2 步或第 3 步的规则来打破僵局:
要更改第 2 步,请将凭据评估添加到旧资源的响应中。先前建议auto_prepend_file()
的答案正朝着这个方向发展,但仅适用于PHP 遗留文件——图像、html 等不走运。
更改第 3 步,找到一种无需 UA 直接请求资源即可交付旧资源的方法。一种可能性是让处理程序从文件系统中获取资源,并使用readfile()
和一些 HTTP 标头管理将其放在网络上。
也许这些的组合会为您解决问题:auto_prepend_file()
将身份验证处理应用于旧版 PHP,readfile()
用于非 PHP 内容。
【讨论】:
【参考方案2】:您只需要一个简单的验证功能。用户要么被允许访问资源,要么被禁止。所以首先设置上下文:
$rules = rules_load();
$uri = $_SERVER['QUERY_STRING'];
$userIsLoggedIn = user_is_logged_in();
接下来我们有上述验证函数,默认情况下应该返回false
,并将上下文作为参数:
$validation = function (array $rules, $uri, $userIsLoggedIn)
$permitted = false;
return $permitted;
;
那么逻辑就很简单了:
if ($validation($rules, $uri, $userIsLoggedIn))
# can pass
echo "can pass";
else
# login first
echo "login first";
这自然已经让您“先登录”。美好的。我们将很快更改该函数的参数。让我们看看$rules
和$uri
是如何相互支持的。
每个规则都可以匹配一个 URI,至少 path 可以。让我们拆分规则:
<sign><path>
sign := [+-]
path := <segment>*/
segment := /[a-z]+
规则匹配或不匹配$uri
。如果匹配,则 sign 决定这意味着什么。
所以实际上符号指定了两个组,可以说$uri
是否匹配。这又是一个简单的函数,首先将规则数组按符号过滤,然后按路径过滤。
考虑一个具有三个输入参数的函数,它以与 uri 匹配的数组形式返回所有规则的子集:
function ($sign) use ($rules, $uri)
return array_reduce($rules, function ($a, $v) use ($rules, $sign, $uri)
$v[0] === $sign && false !== strpos($uri, substr($v, 1)) && $a[] = $v;
return $a;
, array());
;
这或多或少是对array_reduce
的调用。因此,我们假设这将与一个名为 $match
的变量相关联,然后该变量可以替换 $rules
和 $uri
作为 $validation
函数的参数。
$validation = function ($match, $userIsLoggedIn)
所以剩下的部分就是现在制定验证条件:
$permitted = $userIsLoggedIn;
默认情况下,如果用户已登录,则授予权限。只有在用户没有登录的情况下,如果-组不匹配,+组匹配,我们可以授予权限。出于安全原因, - 组应该放在第一位并覆盖任何 + 规则:
$permitted = $userIsLoggedIn ?: !$match('-') && $match('+');
剩下的就是返回那个状态:
return $permitted;
;
由于这个函数相当简单,我们可以发出它。现在完整的代码:
$rules = rules_load();
$uri = $_SERVER['QUERY_STRING'];
$userIsLoggedIn = user_is_logged_in();
$match = rules_match($rules, $uri);
$permitted = $userIsLoggedIn ?: !$match('-') && $match('+');
if ($permitted)
# can pass
echo "can pass";
else
# login first
echo "login first";
/**
*/
function rules_match(array $rules, $uri)
return function ($sign) use ($rules, $uri)
return array_reduce($rules, function ($a, $v) use ($rules, $sign, $uri)
$v[0] === $sign && false !== strpos($uri, substr($v, 1)) && $a[] = $v;
return $a;
, array());
;
【讨论】:
这个答案是什么?! Mike 想知道重定向循环,而你重写了它的规则检查??? @BigBoss:彻底阅读问题。当他将会话检查放在那里时,这些问题就不存在了。除非他不把它放进去,否则他总是会遇到循环问题。由于实现是隐藏的,因此没有太多要回答的问题。迈克写道,他将实现这一点。【参考方案3】:只是一个想法,但也许您不需要为 mod_rewrite 苦苦挣扎。如果你想处理 PHP 中的所有内容,为什么不在你的 VHOST 中添加一个前置文件?
php_value auto_prepend_file handler.php
它将包含在任何 PHP 脚本之前,如果需要,您可以重定向。
【讨论】:
我认为这个解决方案很有意义。您的问题提出了一个非常复杂的解决方案,而这个非常简单。【参考方案4】:您是否有不想使用 apache auth 的原因?我认为它会简单得多。 http://httpd.apache.org/docs/2.2/howto/auth.html
您可以在虚拟主机中按目录指定访问规则,您的用户信息可以在平面文件或数据库中。
【讨论】:
缺乏经验可能是原因;-) 我会看看这个,谢谢 查看后,问题是这些目录访问规则需要根据管理面板的输入动态更改。 嗨,迈克;他们多久改变一次?您可以在需要时动态重新生成您的 apache 配置(并重新启动 apache)。 它们一天变化多次。我考虑过动态重新生成 apache 配置,但这似乎有点 hackish 重新生成 .htaccess 文件不需要重启 Apache2。以上是关于站点安全正则表达式处理程序? (PHP) [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
Nginx位置正则表达式来处理/ sub /目录中多个WordPress站点的永久链接