Apache htaccess:如果 REQUEST_URI 与 cookie 值不匹配,则拒绝
Posted
技术标签:
【中文标题】Apache htaccess:如果 REQUEST_URI 与 cookie 值不匹配,则拒绝【英文标题】:Apache htaccess: Deny if REQUEST_URI not match cookie value 【发布时间】:2019-03-14 00:10:09 【问题描述】:所以,在整个社区寻找解决方案后,我的问题如下:
我在 Wordpress 环境中工作,Apache 服务器。我在上传中有一个名为 /restricted/
的文件夹。此处的所有内容(任何文件扩展名)只有在以下情况下才能访问::
如果这些条件失败,则会提供图像。在这个/restricted/
文件夹中,我得到了一个.htaccess
文件。一切都必须(首选)在那个 htaccess 文件中完成,而不是在 root htaccess 文件中。
cookie是functions.php设置的,没问题 部分。而关于安全性的 cmets 不是这里的问题
这是一个 url 示例(本地主机):http://localhost/komfortkonsult/wp-content/uploads/restricted/some-file.jpg?r=870603c9d23f2b7ea7882e89923582d7
第一个条件设置了一个名为 custom_cookie 的 cookie,一切都在工作:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /komfortkonsult/
RewriteCond %REQUEST_URI ^.*uploads/restricted/.*
RewriteCond %HTTP_COOKIE !custom_cookie
RewriteRule . /komfortkonsult/restricted.png [R,L]
</IfModule>
但是,下一部分我完全出局了,但是我尝试失败了以下方法:
RewriteCond %HTTP_COOKIE custom_cookie=(.*)$
RewriteCond %1::%REQUEST_URI ^(.*?)::/\1/?
RewriteRule . /komfortkonsult/restricted.png [R,L]
同样:
RewriteCond %QUERY_STRING ^r=(.*)$
RewriteRule ^/ - [E=COOKIE_MATCH:%1]
RewriteCond %HTTP_COOKIE !custom_cookie="%ENV:COOKIE_MATCH"
RewriteRule . /komfortkonsult/restricted.png [R,L]
同样:
RewriteCond %HTTP_COOKIE custom_cookie=([^;]+) [NC]
RewriteCond %REQUEST_URI !%1 [NC]
RewriteRule . /komfortkonsult/restricted.png [R,L]
等等。我真的想把它保存在.htaccess
中,而不是通过.php
文件调用进行验证。但是如果这是我架构的唯一解决方案,请提供一个完整的工作示例(不是 foo=bar,你的重定向在这里...)
我的目标的任何其他方法都是受欢迎的。
非常感谢您帮我解决这个问题。
/Intervik
更新(在接受答案并工作后)使用示例
目标是在 Wordpress 单一安装中一层保护。如果A) ,所有上传并附加到页面的媒体、图像或其他文件都被隐藏用户未登录或B)用户已登录但没有'edit_post'功能。
但限制仅适用于上传到名为/restricted/
的唯一文件夹的文件。该文件夹位于 Wordpress 原始 /uploads/
根目录中。此受限材料不允许直接链接或被搜索引擎等访问。不允许浏览器缓存,并且限制必须在注销后立即生效。还有更多……但我想你明白了。
命名空间'custom_cookie'
只是一个示例。显示 Wordpress 安装的示例位于 localhost 的子文件夹中。喜欢h**p://example.com/workspace/
。如果在 root 中,则删除 'workspace/'
。
cookie 架构,functions.php
function intervik_theme_set_custom_cookie()
if(is_user_logged_in())
global $current_user;
if(current_user_can('edit_posts'))
if(!isset($_COOKIE['custom_cookie']))
$cookie_value = $current_user->ID . '|' . $current_user->user_login . '|' . $current_user->roles;
$salt = wp_salt('auth');
$cookie_hash = hash_hmac('md5', $cookie_value, $salt);
setcookie('custom_cookie', $cookie_hash, time()+36, '/');
$_COOKIE['custom_cookie'] = $cookie_hash;
else
$cookie_value = $current_user->ID . '|' . $current_user->user_login . '|' . $current_user->roles;
$salt = wp_salt('auth');
$cookie_hash = hash_hmac('md5', $cookie_value, $salt);
if($cookie_hash != $_COOKIE['custom_cookie'])
setcookie('custom_cookie', '', 1, '/');
unset($_COOKIE['custom_cookie']);
else
if(isset($_COOKIE['custom_cookie']))
setcookie('custom_cookie', '', 1, '/');
unset($_COOKIE['custom_cookie']);
else
if(isset($_COOKIE['custom_cookie']))
setcookie('custom_cookie', '', 1, '/');
unset($_COOKIE['custom_cookie']);
add_action('init', 'intervik_theme_set_custom_cookie');
如您所见,对于 每个有效用户,每个 cookie 是唯一的,对于每 +36 秒的时间段(足够加载页面 - 但使用 +120 2分钟)。此“令牌”应用于发送到服务器的每个请求:
附件网址过滤器的链接:
function intervik_restricted_wp_get_attachment_url($url, $post_id)
if(strpos($url, '/restricted/') !== FALSE)
if(isset($_COOKIE['custom_cookie']))
$url = add_query_arg('r', $_COOKIE['custom_cookie'], $url);
return $url;
add_filter('wp_get_attachment_url', 'intervik_restricted_wp_get_attachment_url', 10, 2);
我们不允许任何其他查询字符串。备注,必须为尺寸添加更多过滤器,例如wp_get_attachment_image_src
等。但是直接链接到媒体,这就足够了。
将
if(current_user_can('edit_posts')
替换为另一个if(is_user_logged_in() ...
将所有内容更改为仅登录/退出 用户。然后使用 if(!is_admin() && strpos($url, '/restricted/')!== FALSE) ...
跳过管理后端中的过滤器
最后是.htaccess
文件,位于uploads/restricted/
文件夹的根目录中:
# BEGIN Intervik
Options +FollowSymLinks
Options All -Indexes
<IfModule !mod_rewrite.c>
Deny from all
</IfModule>
<IfModule mod_headers.c>
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires 0
</IfModule>
RewriteEngine On
RewriteCond %HTTP_COOKIE::%QUERY_STRING !\bcustom_cookie=([0-9a-f]32)\b.*::r=\1(&|$)
RewriteRule . /workspace/restricted.png? [R,L]
# END Intervik
我还在 Wordpress 安装根目录中放置了漂亮的 PNG IMAGE“受限访问超时”。这也作为非有效管理员的图书馆管理区域的缩略图。上传过滤器或后端是另一个区域。
我们不是在这里保护英格兰的财务计划,但我们想保留 为一个组织和一些来自 Google 和来自的图片 你的妻子。
请发表评论
它确实有效,欢迎您评论缺陷或安全风险。然而,在我们的安装中,在这一层之上还有另一层使用 PHP 进行验证,但我们需要速度来处理不那么重要的事情。
【问题讨论】:
这似乎是一种非常有趣的方法——以这种方式路由值。如果我理解正确,示例是当 Wordpress 安装在子文件夹中时(我想是 localhost 环境)? 是的,我在上次编辑时添加了有关示例的信息,位于 Wordpres 子文件夹安装中,谢谢 Anna。 除了简单地确保它们相同之外,您如何验证 cookie 和 URL 参数值?add_filter('wp_get_attachment_url'
过滤器将用户 cookie 值 填充为r=query string
。人们必须明白,此解决方案需要 由 id 加载 的图像(如画廊或菜单),而不是在帖子和页面中硬编码嵌入 src:s。但是可以过滤内容和 wp_get_attachment_imagesrc 以获得更复杂的输出。
我确认它有效。但是如果 edit_posts 层被删除,它更容易调整,并且仅用于登录和注销。删除'|' . time()
并将+36 更改为2 分钟后,一切都感觉更稳定了。漂亮的 "restricted file" PNG 已在缓存中,重新登录可能会在此处刷新...
【参考方案1】:
您在不同的尝试中获得了一些正确的位,但您需要以正确的顺序将它们组合在一起。
请尝试以下方法:
RewriteEngine On
# custom_cookie value is 32 char hex and must match the value of the "r" URL parameter
RewriteCond %HTTP_COOKIE::%QUERY_STRING !\bcustom_cookie=([0-9a-f]32)\b.*::r=\1(&|$)
RewriteRule ^ /komfortkonsult/restricted.png [QSD,R,L]
QSD
标志 (Apache 2.4+) 是从重定向 URL 中删除查询字符串所必需的。或者,如果您仍在使用 Apache 2.2,那么您可以将 ?
附加到 susbstitution。
请注意,此处不需要RewriteBase
。 <IfModule>
也应该被删除。 <IfModule mod_rewrite.c>
包装器仅在打算在没有 mod_rewrite 可用的情况下工作时才需要。它不是。如果 mod_rewrite 不可用,那么您的条件将简单地失败并且访问将不受限制。在这种情况下,最好是出现错误并禁止访问(所有人)。
假设:
cookie 值为 32 个字符的十六进制值(如您的示例所示)。r
URL 参数始终是第一个 URL 参数(如您的示例中所示)。
您提到“任何文件扩展名”,但是,如果首先请求图像,重定向到图像才真正“有效”。如果您有图像以外的文件,最好简单地返回 403 Forbidden。 (严格来说,发送 403 是正确的响应,而不是 302,然后是 200 OK。)要发送 403,只需将 RewriteRule
指令更改为:
RewriteRule ^ - [F]
这是如何工作的......
除一个示例外,所有示例都遗漏了重要的一点,即r
URL 参数是 查询字符串 的一部分,而不是 URL 路径。 REQUEST_URI
服务器变量仅包含 URL 路径,特别是不包括查询字符串。要匹配查询字符串,您需要与QUERY_STRING
服务器变量进行比较。
%HTTP_COOKIE::%QUERY_STRING
- cookie
HTTP 请求标头与 查询字符串 使用分隔符 (::
) 连接,保证不会出现在任一值中。这形成了 TestString。
!\bcustom_cookie=([0-9a-f]32)\b.*::r=\1(&|$)
- 这是与 TestString 匹配的 CondPattern。 \b
是一个单词边界,所以我们只匹配这个特定的 cookie。此 cookie 的值是使用([0-9a-f]32)
捕获的。然后,我们跳过 cookie 标头中的任何剩余字符,直到到达分隔符 (::
)。在此之后,我们将匹配 查询字符串(TestString 中 QUERY_STRING
服务器变量的值)。 “魔法”是\1
对第一个捕获组的反向引用,即。 cookie 值。
CondPattern 上的 !
前缀否定了整个模式。因此,当此模式不匹配时,条件成功,即。当 cookie 和 URL 参数的值不同(或根本不存在)时。
为什么您的尝试没有成功...
这假定您的 cookie 是RewriteCond %HTTP_COOKIE custom_cookie=(.*)$ RewriteCond %1::%REQUEST_URI ^(.*?)::/\1/?
Cookie
标头中的最后一个 cookie。这很难保证。
您正在尝试将 cookie 值与整个 URL 路径 (REQUEST_URI
) 匹配,因此这永远不会匹配。它假定您的 URL 采用以下形式:http://localhost/870603c9d23f2b7ea7882e89923582d7
。
RewriteCond %QUERY_STRING ^r=(.*)$ RewriteRule ^/ - [E=COOKIE_MATCH:%1] RewriteCond %HTTP_COOKIE !custom_cookie="%ENV:COOKIE_MATCH"
好的,您正在检查 查询字符串 中的 URL 参数值。不过……
第一个RewriteRule
永远不会匹配,因为 URL 路径在每个目录 (.htaccess
) 上下文中永远不会以斜杠开头。因此,永远不会设置 COOKIE_MATCH
环境变量。
CondPattern 是一个正则表达式,而不是一个普通字符串,所以 %ENV:COOKIE_MATCH
不会被计算 - 它被视为一个文字字符串。您还用双引号将其括起来,这也不是 cookie 值的一部分。
同样,您是在比较 URL 路径,而不是查询字符串。但是,如上所述,RewriteCond %HTTP_COOKIE custom_cookie=([^;]+) [NC] RewriteCond %REQUEST_URI !%1 [NC]
%1
反向引用不会在 CondPattern 中进行评估,因此无论如何这都被视为文字字符串。
这就是为什么%VARIABLE
(和%1
等)表达式没有在CondPattern中求值的原因,我们需要使用看似复杂的表达式,该表达式使用如下形式的正则表达式反向引用:
%VAR1@@%VAR2 ^(.+)@@\1$
【讨论】:
感谢您的专业解答。 我确认答案有效。我知道我的想法应该是可能的,但我无法通过搜索引擎在任何地方找到此任务...为了清除“任何文件扩展名”,我提到该规则必须适用到该文件夹中的任何内容,而不仅仅是图像。但是重定向从 Wordpress 安装根目录提供了一个漂亮的 png 图像“受限文件 - 访问超时”(没有文件夹 url 看起来很漂亮)。再次感谢您抽出宝贵时间回答问题并为 Stack 社区做出贡献。 最后,在看到这个问题之前,我们也找不到任何提示。找了几天。这也为我们工作。 如果值(长度)未知,任何人都可以评论如何更改32)\b.*::
? 或者可能因每个用户而异? (不使用哈希)
@AnnaEricson 32
不是严格要求的,例如,您可以用+
替换它,它仍然可以“工作”。但是,这似乎更符合 OP 的要求,并且在这种情况下可能更有效。通常,正则表达式应尽可能具体。 OP 似乎正在设置一个 32 char 十六进制值,因此我们不妨对其进行验证,如果不满足此条件,则尽早失败。请记住,cookie 是 用户 提供的数据,因此可能包含任何内容。 (32
量词正好匹配前面模式的 32 个字符,不多也不少。)
@AnnaEricson 如果值长度未知,则将32
更改为+
1 个或多个字符。或者,如果您知道长度在 10 到 50 个字符之间,那么请包含一个范围量词,例如。 10,50
。此外,如果这不是十六进制值,那么您需要根据您的值将前面的字符类从 [0-9a-f]
更改为更具体(或通用)的内容。以上是关于Apache htaccess:如果 REQUEST_URI 与 cookie 值不匹配,则拒绝的主要内容,如果未能解决你的问题,请参考以下文章
apache_conf 如果从开发站点丢失,请抓取实时站点文件 - htaccess
apache .htaccess 重写 - 我可以把它移到 httpd.conf