Apache htaccess:如果REQUEST_URI与Cookie值不匹配,则拒绝

时间:2018-10-09 09:04:57

标签: .htaccess url mod-rewrite cookies match

因此,在整个社区中寻找解决方案后,我的问题如下:

我在Wordpress环境中的Apache服务器中工作。我在上传文件中有一个名为/restricted/的文件夹。此处的所有内容(任何文件扩展名)仅在以下情况下可访问

  • 设置了一个名为“ custom_cookie”的cookie
  • 并且,此Cookie值必须与URL请求的部分匹配

如果这些条件失败,则将提供图像。在这个/restricted/文件夹中,我得到了一个.htaccess文件。一切都必须(最好)在该htaccess文件中完成,而不是不在根 htaccess文件中。

  

cookie是由functions.php设置的,这没问题   部分。关于安全性的评论不是这里的问题

这是一个网址示例(本地主机):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/。如果是根用户,请删除'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');

如您所见,在每个+36秒的时间内,每个Cookie 对于每个有效用户都是唯一的(足以加载页面-但使用+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() ...将所有内容更改为仅登录/注销   用户。然后使用i f(!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的另一层验证,但是对于不太重要的内容,我们需要速度。

1 个答案:

答案 0 :(得分:2)

您在进行不同的尝试时会得到一些正确的信息,但是您需要以正确的顺序将它们组合在一起。

请尝试以下操作:

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参数始终是 first 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参数的值不同(或根本不存在)。

为什么您的尝试不起作用...

RewriteCond %{HTTP_COOKIE} custom_cookie=(.*)$
RewriteCond %1::%{REQUEST_URI} ^(.*?)::/\1/?
  • 这假设您的cookie是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值的一部分。
RewriteCond %{HTTP_COOKIE} custom_cookie=([^;]+) [NC]
RewriteCond %{REQUEST_URI} !%1 [NC]
  • 同样,您要与URL路径而不是查询字符串进行比较。但是,如上所述,在{em> CondPattern 中不评估%1后向引用,因此无论如何这都被视为文字字符串。

这就是为什么在 CondPattern 中不评估%{VARIABLE}(和%1等)表达式的原因,我们需要使用看似复杂的表达式,该表达式使用的正则表达式反向引用表格:

%{VAR1}@@%{VAR2} ^(.+)@@\1$