6

我想知道是否会有这样的事情。我想检查文件的大小,然后根据它做 htaccess 规则。例如:

# like this line
CheckIf {REQUESTED_FILE_SIZE} 50 # MB
AuthName "Login title"
AuthType Basic
AuthUserFile /path/to/.htpasswd
require valid-user

很明显,我想让某些具有特定文件大小的文件仅对某些用户可用(使用身份验证)

任何想法都值得赞赏。

更新#1

应该在htaccess中完成

更新#2

有很多文件,它们的 URL 已经发布在博客中。因此不能将较大的文件分开到另一个文件夹并更新每个帖子,而且文件大小的限制将来可能会改变。

更新#3

这是一个安装了 PHP & helicon App 的 Windows 服务器

更新#4

有些人对真正的问题感到困惑,我也没有弄清楚。

.htaccess + PHP 文件用于身份验证(使用 API)和检查文件大小+所有可下载的文件都在同一个服务器上,我们的网站托管在不同的服务器上。

4

6 回答 6

3

显然 .htaccess 无法检查请求的文件大小并采取相应措施。你可以做的是利用External Rewriting Program feature of RewriteMap

您需要先定义RewriteMap这样的 Apache 配置:

RewriteMap checkFileSize prg:/home/revo/checkFileSize.php

然后在您的 .htaccess 中通过传递定义这样的规则:

RewriteRule - ${checkFileSize:%{REQUEST_FILENAME}}

%{REQUEST_FILENAME}传递给 STDIN 上的 PHP 脚本。

然后,/home/revo/checkFileSize.php您可以在里面放置 PHP 代码来检查文件的大小并相应地采取行动,例如重定向到显示基本身份验证对话框的 URI。

于 2013-08-23T10:41:30.063 回答
2

我认为@Paolo Stefan 和@anubhava 的两个答案都是有效的(+1)。

请注意,使用 RewriteMap 将强制修改 apache 配置,而不仅仅是 .htaccess 文件。如果您稍微考虑一下性能,实际上您应该将 .htaccess 文件中的所有内容放入<directory /same/filesystem/path/as/the/.htaccess/file/>指令中并放入AllowOverride NoneVirtualHost 配置中。通过避免每个查询的 Apache 文件 I/O 和动态检查配置文件设置,您肯定会获得一些速度(.htaccess 文件真的很糟糕)。所以RewriteMap在 .htaccess 中不可用的事实应该不是问题。

这两个答案提供了一种根据文件大小动态更改身份验证标头的方法。现在,您在问题中忘记提及的一个重要事实是,这些文件与 PHP 文件在同一台服务器上不直接可用,而且您不想在每次下载时启动脚本。

使用当前的@anubhava 解决方案,您将在每次访问时在操作系统上调用文件大小,当然该脚本应该在文件存储服务器上运行。

一种解决方案可能是将文件大小的索引存储在某个地方(专用数据库或键值存储?)。您可以在每次下载后提供此索引,您可以管理一些异步任务来维护它。然后在文件存储服务器的 apache 配置上,您将不得不启动一个脚本来检查文件大小。使用 RewriteMap 你有几个选项:

  • 使用带有关键字的非常快速的脚本prg:(用 C、Perl 编写的任何东西,你不依赖于 PHP),在这个数据存储中请求这个文件大小的索引,甚至fastdbd:直接在 apache 中执行 SQL 查询。但这意味着对每个请求进行查询,因此您有其他解决方案。
  • 直接使用带关键字的o 映射文件txt:,为每个文件名计算匹配大小,不再查询,只需
  • 更好的是,将此文件的哈希图与 dbm:` 关键字一起使用。

对于最后两个选项,文件大小索引是该文本文件的文本文件或散列版本。Apache 正在缓存 hashmap 并在重新启动更改文件的修改时间时重新计算缓存。因此,您只需在每次下载后重新计算此哈希图,即可在 RewriteRule 中获得非常快速的文件大小检查,如 anubhava 所示,但使用

RewriteMap checkFileSize dbm:/path/to/filesize_precomputed_index.map

您还可以尝试在文件服务器上使用mod_security并检查Content-Length标头以添加 HTTP Auth。检查此线程以获取有关该主题的答案的开头。但是 mod_security 配置并不是一件容易的事。

于 2013-08-28T08:52:26.817 回答
2

我分两步完成:

1:htaccess 将所有请求重定向到一个 php 脚本,假设你有你的文件/test/,你想让它全部由 处理/test/index.php,例如:

RewriteEngine On
RewriteBase /test
RewriteCond %{REQUEST_URI} !/test/index.php
RewriteRule ^(.+)? /test/index.php?file=$1 [L]

RewriteCond只是为了避免循环请求。

2:index.php脚本根据请求的文件大小执行所有身份验证逻辑,如下所示:

define('LIMIT_FILESIZE',50*1024*1024); // eg.50Mb
define('AUTH_USER', 'myuser');         // change it to your likes
define('AUTH_PW','mypassword');        // change it to your likes

if( filesize($_GET['file'])>LIMIT_FILESIZE ){
  if( !isset($_SERVER['PHP_AUTH_USER']) ) {
    header('WWW-Authenticate: Basic realm="My realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Canceled';
    exit;
  } 
  else if( $_SERVER['PHP_AUTH_USER']!=AUTH_USER &&
           $_SERVER['PHP_AUTH_PW']!=AUTH_PW ) {
    header('HTTP/1.0 401 Unauthorized');
    echo 'Wrong credentials';
    exit;
  }
}

// If we're here, it's fine (filesize is below or user is authenticated)
// offer file for download
$file = rawurldecode($_GET['file']);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file( $finfo, $file );
header("Content-type: ".$mime );
header("Content-Disposition: attachment; filename=".basename($file));
include( $file );

它有许多可能的改进,但它应该作为一个基础。

于 2013-08-22T09:20:03.483 回答
1

不是直接的,而是在文件系统方面稍作修改就可以做到。

如果这是一个用户上传和下载的系统,您可以关闭Content-Length标题mod_rewrite以将较大的文件放入单独的目录中。(或者如果您可以在上传时以其他方式移动它们)

接下来,在包含较大文件的目录中,您将其设置为所有文件都需要身份验证。

最后使用 mod_rewrite 中的存在测试来透明地将用户重定向到 large_files 目录(如果文件在那里)。

如果您无法移动文件,您可以使用符号链接来设置两种布局。

于 2013-08-22T08:19:32.610 回答
1

据此支持CondPattern , 检查指定的TestString是否是具有非零大小的常规文件。附加的补丁扩展了支持与任意大小进行比较的选项。mod_rewrite"-s" "-s"

于是被问到:

CheckIf {REQUESTED_FILE_SIZE} 50 # MB

应该使用这个.htaccess代码:

RewriteCond %{REQUEST_FILENAME} -s=52428800
于 2015-04-16T09:21:28.787 回答
0

当时我问了 Apache 2.4 已经发布的问题,所以这个答案可能是正确的。

阿帕奇表达式

从 Apache 2.4 开始,引入了一种称为Expressions的新功能。据此,您可以在指令中使用一些函数,也可以与RewriteCond.

幸运的是,有一个名为的函数能够与比较运算符filesize()一起比较文件大小: -et -gt -ge -lt -le -ne

说-但是文档缺少有关此功能的信息-以下是比较文件大小的相应规则:

RewriteCond expr "filesize('%{REQUEST_FILENAME}') -gt 52428800"
RewriteRule ** **

在内部使用表达式RewriteCond应该在这个语法中完成:

RewriteCond expr "..."

BNF :

expr        ::= "true" | "false"
              | "!" expr
              | expr "&&" expr
              | expr "||" expr
              | "(" expr ")"
              | comp

您可以在文档页面找到完整的BNF 。

于 2015-11-23T18:33:37.967 回答