验证访问令牌并将下载重定向到另一台服务器

问题描述

我有一个 Server A,它有一个包含有效下载令牌的数据库

如果用户提供有效的令牌(存在于数据库中),他们将可以下载一个文件(> 2 GB)。目前,我这样做(详见 Fastest Way to Serve a File Using PHPDownloading files with download.php):

<?PHP
$ok = check_token_in_database($_GET['token']);   // internally uses a sqlite DB
$file = "bigfile.zip";
if ($ok) {
    header("X-Sendfile: /path/to/" . $file);
    header("Content-type: application/octet-stream");
    header('Content-disposition: attachment; filename="' . $file . '"');
}

它有效,但现在我需要减轻 Server A负载,如果令牌有效,我希望从另一个 Server B 提供文件.我在想:

<?PHP
$ok = check_token_in_database($_GET['token']);
if ($ok) {
    header("Location: https://server_b.example.com/obfuscated_url_ff87a45d76apZ/bigfile.zip");

但是,任何人都可能能够找到目标链接 https://server_b.example.com/obfuscated_url_ff87a45d76apZ/bigfile.zip 他们可以与其他人分享,我不想要。

如何处理这种情况,而不必将令牌数据库和令牌检查移动到Server B

解决方法

您可以使用 JWT 来生成令牌。在有效载荷中,您可以存储用户的 IP 地址以防止链接共享。

我不确定要为 PHP 使用哪个库,但让我们以这个库为例: https://github.com/miladrahimi/php-jwt

在服务器 A 上生成令牌:

// Use HS256 to generate and parse tokens
$signer = new HS256(JWT_SECRET_KEY);

// Generate a token
$generator = new Generator($signer);
$jwt = $generator->generate(['file' => 'bigfile.zip','ip' => $_SERVER['REMOTE_ADDR']);

在服务器 B 中,您验证并解析令牌:

$jwt = &$_GET['token'];
$signer = new HS256(JWT_SECRET_KEY);

// Add Validation (Extend the DefaultValidator)
$validator = new DefaultValidator();
$validator->addRule('ip',new EqualsTo($_SERVER['REMOTE_ADDR']));

// Parse the token
$parser = new Parser($signer);

try {
    $claims = $parser->parse($jwt);
    // Serve $claims['file'] here.
} catch (ValidationException $e) {
    // Validation failed.
}

在两台服务器中你都应该定义密钥:

define('JWT_SECRET_KEY','your-long-secret-key-here');

当然,您可以添加更多验证、令牌过期等。

如果您只想将私钥保留在服务器 A 上,则应使用 RSA 算法,然后使用服务器 A 上的私钥生成令牌,并使用公钥解析服务器 B 上的令牌。 (图书馆的 README 中有一个例子)