3

我正在尝试将 Perl 的do EXPR函数用作穷人的配置解析器,使用第二个 .pl 文件,该文件只返回一个列表作为配置信息。(我认为这可能是 的理想用途do,尤其是因为我可以do or die在我的代码中写“”。)这是一个例子:

主文件

# Go read the config file
my %config = do './config.pl';

# do something with it
$web_object->login($config{username}, $config{password});

配置文件

# Configuration file for main script
(
  username => "username",
  password => "none_of_your_business",
  favorite_color => "0x0000FF",
);

阅读Perldocdo提供了很多关于相对路径的有用建议 - 搜索 @INC 和修改 %INC,关于 5.26 的特殊警告不搜索“。” 等等。但它也有这些位:

# 加载确切的指定文件(./ 和 ../ 特殊情况) ...


将 do 与相对路径一起使用(./ 和 ../ 除外),例如...

然后它实际上从不费心解释“./”或“../”的特殊情况路径处理 - 一个重要的遗漏!

所以我的问题都是关于“当你真正发生了什么do './file.pl';”的变体?例如...

  • 尽管 CWD 从 @INC 中删除,但此语法在 5.26 中是否仍然有效?
  • 无论如何,从谁的角度来看是“./”:Perl 二进制文件、执行的 Perl 脚本、来自用户 shell 的 CWD,还是其他?
  • 是否存在需要注意的安全风险?
  • 这比修改@INC 并仅使用基本文件名更好还是更差?

任何见解都值得赞赏。

4

1 回答 1

5

好的,所以-首先,我不确定您config.pl是否真的是正确的方法-它不perl适合初学者,因为它无法编译。不管怎样,尝试评估东西以“解析配置”通常不是一个好计划——它很容易出现令人不快的故障和安全漏洞,所以应该在需要时保留。

我会敦促您通过以下方式以不同的方式进行操作:

把它写成一个模块

像这样的东西:

package MyConfig;

# Configuration file for main script
our %config = (
   username       => "username",
   password       => "none_of_your_business",
   favorite_color => "0x0000FF",
);

然后你可以在你的主脚本中:

use MyConfig; #note - the file needs to be the same name, and in @INC

并访问它:

print $MyConfig::config{username},"\n"; 

如果你不能把它放在现有的@INC- 这可能有你不能的原因,FindBin让你使用相对于你的脚本位置的路径:

use FindBin; 
use lib "$FindBin::Bin"; 
use MyConfig;

将您的“配置”编写为已定义的可解析格式,而不是可执行代码。

YAML

YAML对于配置文件来说非常可靠,尤其是:

use YAML::XS;

open ( my $config_file, '<', 'config.yml' ) or die $!; 
my $config = Load ( do { local $/; <$config_file> });

print $config -> {username};

您的配置文件如下所示:

username: "username"
password: "password_here"
favourite_color: "green"
air_speed_of_unladen_swallow: "african_or_european?"

(YAML 还支持多维数据结构、数组等。不过你似乎不需要这些。)

JSON

JSONbased 看起来很相似,只是输入是:

{
  "username": "username",
  "password": "password_here",
  "favourite_color": "green",
  "air_speed_of_unladen_swallow": "african_or_european?"
}

你读它:

use JSON;
open ( my $config_file, '<', 'config.json' ) or die $!; 
my $config = from_json ( do { local $/; <$config_file> });

使用相对路径进行配置:

您完全不必担心@INC。您可以简单地基于相对路径使用......但更好的选择是不这样做,FindBin而是使用 - 它可以让您指定“相对于我的脚本路径”,这更加健壮。

 use FindBin;
 open ( my $config_file, '<', "$FindBin::Bin/config.yml" ) or die $!; 

然后你就会知道你正在阅读与你的脚本在同一目录中的那个,无论它是从哪里调用的。

具体问题:

无论如何,从谁的角度来看是“./”:Perl 二进制文件、执行的 Perl 脚本、来自用户 shell 的 CWD,还是其他?

当前工作目录通过进程向下传递。所以默认情况下用户的shell,除非perl脚本执行chdir

是否存在需要注意的安全风险?

任何时候您“评估”某些东西,就好像它是可执行代码(并且EXPR可以是)存在安全风险。它可能并不大,因为脚本将以用户身份运行,而用户是可以篡改的人CWD。核心风险是:

  • 用户位于“不同”目录中,其他人在该目录中放置了恶意内容供他们运行。(例如,想象一下“config.pl”rm -rf /*在其中)。也许/tmp他们不小心“运行”了一个“config.pl”?
    • 你正在输入的东西eval有一个错字,并以时髦和意想不到的方式破坏了脚本。(例如,它可能会$[以难以调试的方式重新定义和混淆程序逻辑)
  • script 在特权上下文中执行任何操作。情况似乎并非如此,但请参阅前一点并想象您是root或其他特权用户。

这比修改@INC 并仅使用基本文件名更好还是更差?

更糟糕的海事组织。实际上只是根本不修改@INC,并使用完整路径,或使用FindBin. 并且不要eval在没有必要的时候做事。

于 2018-04-12T08:44:49.277 回答