5

我预见到允许客户通过 PayPal 从我这里购买某些内容的问题。我将提供多种无形商品。当有人完成对其中一种商品的购买时,他们将被重定向到一个登陆页面——我们称之为“thank_you.php”——它将自动排队下载并允许链接排队下载以防万一自动启动。这将通过将唯一的项目 ID 传递给下载页面(“download.php”)来完成。

此方法本质上是对这些线程的最佳答案的模仿:

PHP生成文件以供下载然后重定向

一个 PHP 脚本让用户从我的网站下载文件而不显示我网站中的实际文件链接?

但是,我担心一旦用户在“thank_you.php”上他们可以下载他们的项目,然后使用 Firebug(或等效)来编辑项目 ID 并下载另一个不同的项目:

<a href="download.php/38a205ec300a3874c867b9db25f47c61">Download Here</a>

<a href="download.php/7c8ddc86c0e4c14517b9439c599f9957">Download Here</a>

我需要你们在这方面比我做得更好的人的想法和帮助:我可以实施什么(以及如何)作为仍然允许相同的客户访问和休闲的解决方案,同时防止这种操纵?

编辑:ID 哈希用于在整个站点中预览和引用该项目,我不怕人们猜测,而是他们在单独的选项卡中浏览该站点以获取其他 ID 并继续下载不同的项目。

4

5 回答 5

4

虽然这些其他答案假设您有一个带有用户名的会话,但听起来好像您刚刚为文件创建了一个哈希以隐藏文件名。换句话说,您还不如在键盘上放一把猴锤,并将其作为您拥有的每个文件的文件名。

然后听起来您担心用户会过来,敲击键盘,并以某种方式最终与您的猴子所做的完全匹配。这不太可能。

更有可能有人会复制并粘贴您的链接并分享它。听起来好像您需要在身份验证方案中至少再添加一层(例如,用户名和项目 ID 的哈希值),或者链接一旦使用就会过期。

从您的评论来看,听起来好像您正在使用哈希来识别网站另一部分的项目,这意味着用户可以通过查看网站另一部分的源来确定项目的哈希。在这一点上,你通过默默无闻的安全很像我在与某人闲聊并说“鱼和猫正在亲热”时使用暗语(例如“鱼意味着约翰,猫意味着丽莎”),同时拥有一张纸旁边的纸上写下任何人都可以看到的映射。听起来您只是想隐藏文件名,以免人们猜到它们。这被称为通过默默无闻的安全性,并不会真正为您带来太多收益。

大多数其他答案都假设一个项目存在,并且它将有多个不同的哈希指向它(例如,file1,hash1、hash2 和 hash3 都是指向它的有效链接)。在这种情况下,他们创建了多个散列,并且每个散列对于某个用户 + 项目都是唯一的。我认为他们还假设网站上的每个人都将下载项目称为item1not hash1,这听起来像你在做什么?

您最好只在代码中的某处创建一个字典,该字典在项目名称和散列之间具有映射,然后仅在下载页面上,将散列替换为名称。同样,这只是通过默默无闻的安全性,可以共享链接,但人们无法在浏览您的网站时获得哈希值。

于 2012-10-04T00:27:30.933 回答
4

我原来的答案:

您将需要存储(在数据库或会话变量中)用户可以访问的项目,您将为每个项目生成一个唯一的随机令牌。该令牌将用于识别购买的物品。将令牌传递到他们将能够下载的页面(在会话变量、POST 参数中,或者作为 url 中的最后一个选项,即 GET)。在您需要下载的页面中,您将使用会话信息查询数据库/会话变量,以识别客户和传递的令牌(但是您传递了它)并检索要下载的文件。

如果您需要保留已购买项目的列表以供重新下载,您也可以这样做,但请记住在用户请求下载时再次创建令牌。如果您愿意,还可以添加到期日期。


现在我已经提到了几个替代方案,然后再次根据引用答案的性质,我想您将需要更多详细信息来说明如何做到这一点。

也许 ernie 是对的,我不应该假设你有一个会话。也许我应该告诉你如何做一个会话。

所以我将采取其中一种实现方式,最简单的方式。


<?php
    //Oh, I'm in a PHP page...
    //check if there is not a session
    if (session_id() != '')
    {
        //Ok, there is no session, let's create one
        session_start();
    }
    //Now we are sure there is a session
    //Let's store in the session the id of the file I want to allow to download
    $_SESSION['download'] = GetFileId();
    //GetFileId will do some mambo jambo expecto patronum to return an id
    //The id will be 38a205ec300a3874c867b9db25f47c61 or something
?>

现在在下载页面......

<?php
    //Oh, I'm in another PHP page...
    //check if there is not a session
    if (session_id() != '')
    {
        //no session? screw you, no download for you
        header('Location: sorry.php');
    }
    else
    {
        //Now we are sure there is a session
        //Let's get from the session the id of the file I want to allow to download
        $id = $_SESSION['download'];
        //Now get the url to redirect to allow the download
        $url = GetUrl($id);
        //GetUrl will do some mambo jambo expecto patronum to return an url
        //Ok, now we are going to return that file...
        //So put the correct MIME type
        header('content-type: image/gif');  //if it is a gif...
        //Load the file
        $contents = file_get_contents($url); 
        echo $contents;
        //That's the only output
        exit();
     }
?>

请注意,我只允许从 PHP 访问该文件,因此我可以先验证用户是否具有访问权限。您不应该允许用户只输入 url(即使他猜不到)并访问文件。因此,如果您正在运行您的服务器,您希望将这些文件放在服务器 Web 文件夹之外,或者如果您使用的是使用 .htaccess(或您的主机提供的其他机制)保护它们的主机。


评论这个解决方案:

它简单,易于实施。然而它也有一些缺点:

  • 如果会话在下载之前终止,则用户将损失金钱*。
  • 没有明确的方法实现重新下载。
  • 它仍然容易受到会话劫持(我知道,这很牵强,但最好是安全的)。

*:假设连接丢失,并且会话在客户端过期。哦,不,我们不需要满意的客户。

所以,你真的,真的,需要用数据库备份它并创建随机令牌,最好有一个到期日期。

于 2012-10-04T00:22:26.483 回答
3

当他们付款时,将可用的下载 ID 和随机哈希存储在付款表中。然后使用哈希来获取 ID。然后,哈希不应与特定产品相关,而应与付款相关。

于 2012-10-04T00:17:26.250 回答
1

您可以实现的最简单的事情之一是跟踪用户购买的日志系统。您可以将请求的 ID 与存储的与用户购买相关的 ID 交叉引用。如果它们不相关,请不要提供文件。

于 2012-10-04T00:18:03.077 回答
1

您需要跟踪用户在数据库中购买了哪些商品。然后download.php 可以检查用户是否购买了他们正在尝试下载的项目。

于 2012-10-04T00:19:36.030 回答