nigelhorne/CGI-Info

GitHub: nigelhorne/CGI-Info

一个Perl编写的CGI环境信息处理库,旨在简化路径与参数解析,并提供基础的Web安全过滤功能。

Stars: 3 | Forks: 4

# CGI-Info [![Appveyor 状态](https://ci.appveyor.com/api/projects/status/1t1yhvagx00c2qi8?svg=true)](https://ci.appveyor.com/project/nigelhorne/cgi-info) [![CircleCI](https://dl.circleci.com/status-badge/img/circleci/8CE7w65gte4YmSREC2GBgW/THucjGauwLPtHu1MMAueHj/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/circleci/8CE7w65gte4YmSREC2GBgW/THucjGauwLPtHu1MMAueHj/tree/main) [![Coveralls 状态](https://coveralls.io/repos/github/nigelhorne/CGI-Info/badge.svg?branch=master)](https://coveralls.io/github/nigelhorne/CGI-Info?branch=master) [![CPAN](https://img.shields.io/cpan/v/CGI-Info.svg)](http://search.cpan.org/~nhorne/CGI-Info/) ![GitHub Workflow 状态](https://img.shields.io/github/actions/workflow/status/nigelhorne/cgi-info/test.yml?branch=master) ![Perl 版本](https://img.shields.io/badge/perl-5.8+-blue) [![安全策略](https://img.shields.io/badge/security-policy-blue.svg)](SECURITY.md) [![推文](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://x.com/intent/tweet?text=Information+about+the+CGI+Environment+#perl+#CGI&url=https://github.com/nigelhorne/cgi-info&via=nigelhorne) # 名称 CGI::Info - 关于 CGI 环境的信息 # 版本 版本 1.11 # 概要 `CGI::Info` 模块是一个 Perl 库,旨在提供有关 CGI 脚本运行环境的信息。 它旨在消除硬编码的脚本细节, 增强代码的可读性和可移植性。 此外,它提供了一个简单的 Web 应用防火墙以增加一层安全性。 很多时候, Perl 程序将脚本名称等信息 硬编码到其源代码中。 一般来说, 硬编码是一种糟糕的风格,因为它会使程序难以阅读,并降低可读性和可移植性。 CGI::Info 试图消除这种情况。 此外,为了辅助脚本调试,当你不在 CGI 环境中运行程序时,CGI::Info 会尝试做一些合理的 处理。 虽然你不应该仅仅依靠它来为你的网站提供安全保障, 但它是另一层防御,积少成多。 ``` use CGI::Info; my $info = CGI::Info->new(allow => { id => qr/^\d+$/ }); my $params = $info->params(); if($info->is_mobile()) { print "Mobile view\n"; } else { print "Desktop view\n"; } my $id = $info->param('id'); # Validated against allow schema ``` # 子程序/方法 ## new 创建一个 CGI::Info 对象。 它接受四个可选参数:allow、logger、expect 和 upload\_dir, 这些参数在 params() 方法中有文档说明。 它接受其他可选参数: - `auto_load` 启用/禁用 AUTOLOAD 功能。 默认为启用。 - `config_dirs` 查找 `config_file` 的位置 - `config_file` 指向一个配置文件,其中包含传递给 `new()` 的参数。 该文件可以是任何常见格式, 包括 `YAML`、`XML` 和 `INI`。 这允许在运行时设置参数。 在非 Windows 系统上, 可以使用以 "CGI::Info::" 开头的环境变量来配置该类。 例如: export CGI::Info::max_upload_size=65536 由于 Windows 系统不区分大小写,因此它在该系统上无法工作。 如果配置文件中有一个名为 `CGI::Info` 的部分, 则仅使用该部分, 以及 `global` 部分(如果存在)。 - `syslog` 接受可选参数 syslog,以将消息记录到 [Sys::Syslog](https://metacpan.org/pod/Sys%3A%3ASyslog)。 它可以是一个用于启用/禁用 syslog 日志记录的布尔值,或者是一个 将传递给 Sys::Syslog::setlogsock 的哈希引用。 - `cache` 用于缓存 IP 查找的对象。 此缓存对象是一个理解 get() 和 set() 消息的对象, 例如 [CHI](https://metacpan.org/pod/CHI) 对象。 - `max_upload_size` 你可以上传的最大文件大小(-1 表示无限制),默认为 512MB。 该类可以在运行时使用环境和配置文件进行配置, 例如, 设置 `$ENV{'CGI__INFO__carp_on_warn'}` 会导致警告使用 [Carp](https://metacpan.org/pod/Carp)。 有关在运行时配置对象构造函数的更多信息, 请参阅 [Object::Configure](https://metacpan.org/pod/Object%3A%3AConfigure)。 ## script\_name 检索正在执行的 CGI 脚本的名称。 这对于 POSTing 很有用, 从而避免了在表单中硬编码路径。 ``` use CGI::Info; my $info = CGI::Info->new(); my $script_name = $info->script_name(); # ... print "
\n"; ``` ### API 规范 #### 输入 无。 #### 输出 ``` { type => 'string', 'min' => 1, 'nomatch' => qr/^[\/\\]/ # Does not return absolute path } ``` ## script\_path 查找脚本的完整路径名。 ``` use CGI::Info; my $info = CGI::Info->new(); my $fullname = $info->script_path(); my @statb = stat($fullname); if(@statb) { my $mtime = localtime $statb[9]; print "Last-Modified: $mtime\n"; # TODO: only for HTTP/1.1 connections # $etag = Digest::MD5::md5_hex($html); printf "ETag: \"%x\"\n", $statb[9]; } ``` ## script\_dir 返回包含脚本的文件系统目录。 ``` use CGI::Info; use File::Spec; my $info = CGI::Info->new(); print 'HTML files are normally stored in ', $info->script_dir(), '/', File::Spec->updir(), "\n"; # or use lib CGI::Info::script_dir() . '../lib'; ``` ## host\_name 根据 CGI 返回当前 Web 服务器的主机名。 如果无法从 Web 服务器确定名称,则使用系统的主机名 作为后备。 这可能与运行 CGI 脚本的机器不同, 一些 ISP 和其他站点在与提供静态内容的机器不同的机器上运行脚本。 很有可能这是在 domain\_name() 前面加上了 'www' 或 'cgi'。 ``` use CGI::Info; my $info = CGI::Info->new(); my $host_name = $info->host_name(); my $protocol = $info->protocol(); # ... print "Thank you for visiting our Website!"; ``` ## domain\_name Domain\_name 是此网站的控制域的名称。 通常它与 host\_name 类似,但不会有 http:// 或 www 前缀。 可以作为类方法调用。 ## cgi\_host\_url 返回运行 CGI 脚本的机器的 URL。 ## params 返回 CGI 参数的哈希列表的引用。 CGI::Info 帮助你在将脚本部署到网站之前进行测试: 如果它不在 CGI 环境中(例如,脚本正在从命令行测试), 则使用程序的命令行参数(键=值对列表),如果没有命令行参数, 则从 stdin 读取键=值行列表。 此外, 你可以给出 --tablet、--search-engine、 \--mobile 和 --robot 之一来模拟这些代理。例如: ``` ./script.cgi --mobile name=Nigel ``` 如果无法确定参数或未给出任何参数,则返回 undef。 如果参数被给出两次或更多次,则这些值将放入一个 逗号分隔的字符串中。 返回的哈希值可以传递给 [CGI::Untaint](https://metacpan.org/pod/CGI%3A%3AUntaint)。 接受四个可选参数:allow、logger 和 upload\_dir。 参数在哈希或哈希引用中传递。 后者更有效,因为它在堆栈上放置的内容更少。 Allow 是你允许的 CGI 参数的哈希列表的引用。 每个条目的值可以是允许的值, 该键允许值的正则表达式, 代码引用, 或 [Params::Validate::Strict](https://metacpan.org/pod/Params%3A%3AValidate%3A%3AStrict) 规则的哈希。 子程序异常正常传播,允许自定义错误处理。 这与现有的正则表达式和 Params::Validate::Strict 模式一起工作。 undef 值表示允许任何值。 不在列表中的参数将被静默忽略。 这有助于阻止对你网站的攻击。 Upload\_dir 是一个字符串,包含要存储上传文件的 目录。 它必须是临时区域中的可写目录。 接受可选参数 logger,用于警告和跟踪。 它可以是一个理解 warn() 和 trace() 消息的对象, 例如 [Log::Log4perl](https://metacpan.org/pod/Log%3A%3ALog4perl) 或 [Log::Any](https://metacpan.org/pod/Log%3A%3AAny) 对象, 代码引用, 数组引用, 或文件名。 allow、logger 和 upload\_dir 参数也可以传递给 构造函数。 ``` use CGI::Info; use CGI::Untaint; # ... my $info = CGI::Info->new(); my %params; if($info->params()) { %params = %{$info->params()}; } # ... foreach(keys %params) { print "$_ => $params{$_}\n"; } my $u = CGI::Untaint->new(%params); use CGI::Info; use CGI::IDS; # ... my $info = CGI::Info->new(); my $allowed = { foo => qr/^\d*$/, # foo must be a number, or empty bar => undef, # bar can be given and be any value xyzzy => qr/^[\w\s-]+$/, # must be alphanumeric # to prevent XSS, and non-empty # as a sanity check }; # or $allowed = { email => { type => 'string', matches => qr/^[^@]+@[^@]+\.[^@]+$/ }, # String, basic email format check age => { type => 'integer', min => 0, max => 150 }, # Integer between 0 and 150 bio => { type => 'string', optional => 1 }, # String, optional ip_address => { type => 'string', matches => qr/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/ }, #Basic IPv4 validation }; my $paramsref = $info->params(allow => $allowed); if(defined($paramsref)) { my $ids = CGI::IDS->new(); $ids->set_scan_keys(scan_keys => 1); if($ids->detect_attacks(request => $paramsref) > 0) { die 'horribly'; } } ``` 如果请求是 XML 请求(即 POST 的内容类型是 text/xml), CGI::Info 会将请求放入 params 元素 'XML',如下所示: ``` use CGI::Info; # ... my $info = CGI::Info->new(); my $paramsref = $info->params(); # See BUGS below my $xml = $$paramsref{'XML'}; # ... parse and process the XML request in $xml ``` 如果未设置 logger 并且我们检测到严重情况,则 Carp。 阻止一些攻击, 例如 SQL 和 XSS 注入, mustleak 和目录遍历, 从而创建一个原始的 Web 应用防火墙 (WAF)。 警告 - 这是一个额外的层,不能替代你的其他安全层。 ### 验证子程序支持 `allow` 参数接受子程序引用以进行动态验证, 支持超越静态正则表达式模式的复杂参数检查。 这些回调: - 接收三个参数:参数键、值和 `CGI::Info` 实例 - 必须返回真值以允许参数,返回假以拒绝 - 可以通过实例访问其他参数以进行上下文验证 基本用法: ``` CGI::Info->new( allow => { # Simple value check even_number => sub { ($_[1] % 2) == 0 }, # Context-aware validation child_age => sub { my ($key, $value, $info) = @_; $info->param('is_parent') ? $value <= 18 : 0 } } ); ``` 高级功能: ``` # Combine with regex validation mixed_validation => { email => qr/@/, # Regex check promo_code => \&validate_promo_code # Subroutine check } # Throw custom exceptions dangerous_param => sub { die 'Hacking attempt!' if $_[1] =~ /DROP TABLE/; return 1; } ``` ## param($field) 从查询字符串获取单个参数。 接受一个可选的单个字符串参数,即要返回的参数。如果 未给出该参数,param() 是不带参数的 params() 的包装器。 ``` use CGI::Info; # ... my $info = CGI::Info->new(); my $bar = $info->param('foo'); ``` 如果请求的参数不在允许列表中,将抛出错误消息: ``` use CGI::Info; my $allowed = { foo => qr/\d+/ }; my $xyzzy = $info->params(allow => $allowed); my $bar = $info->param('bar'); # Gives an error message ``` 如果未给出请求的参数,则返回 undef - $field 要检索的可选字段。 如果省略,则返回所有参数。 ## is\_mobile 如果网站在移动 设备(如智能手机)上被查看,则返回布尔值。 所有平板电脑都是移动设备,但并非所有移动设备都是平板电脑。 可以通过 IS\_MOBILE 环境设置覆盖 ## is\_tablet 如果网站在平板电脑(如 iPad)上被查看,则返回布尔值。 ## as\_string 将 CGI 参数转换为格式化的字符串表示形式,带有可选的原始模式(不转义特殊字符)。 对调试或生成缓存键很有用。 ``` my $string_representation = $info->as_string(); my $raw_string = $info->as_string({ raw => 1 }); ``` ### API 规范 #### 输入 ``` { raw => { 'type' => 'boolean', 'optional' => 1, } } ``` #### 输出 ``` { type => 'string', optional => 1, } ``` ## protocol 返回连接协议,大概是 'http' 或 'https',如果 无法确定则返回 undef。 ## tmpdir 返回可用于创建临时文件的目录的 名称。 该例程优于 ["tmpdir" in File::Spec](https://metacpan.org/pod/File%3A%3ASpec#tmpdir),因为 CGI 程序 通常运行在共享服务器上。话虽如此,如果 tmpdir 找不到更好的 地方,它将回退到 File::Spec->tmpdir()。 如果给出了参数 'default',则使用该目录作为 回退,而不是 File::Spec->tmpdir() 中的值。 没有进行健全性测试,所以如果你给出的默认值是 '/non-existant',它将被返回。 Tmpdir 允许传递选项的引用。 ``` use CGI::Info; my $info = CGI::Info->new(); my $dir = $info->tmpdir(default => '/var/tmp'); $dir = $info->tmpdir({ default => '/var/tmp' }); # or my $dir = CGI::Info->tmpdir(); ``` ## rootdir 返回文档根目录。这优于查看环境中的 DOCUMENT\_ROOT, 因为它也能在非 CGI 脚本运行时工作,这对脚本调试很有用。 这可以作为类或对象方法运行。 ``` use CGI::Info; print CGI::Info->rootdir(); ``` ## root\_dir rootdir() 的同义词,为了与 [CHI](https://metacpan.org/pod/CHI) 兼容。 ## documentroot rootdir() 的同义词,为了与 Apache 兼容。 ## logdir($dir) 获取并设置可用于存储日志的目录的名称。 - $dir 存储日志的目录路径 ## is\_robot 访问者是真人还是机器人? ``` use CGI::Info; my $info = CGI::Info->new(); unless($info->is_robot()) { # update site visitor statistics } ``` 如果检测到客户端试图进行 SQL 注入, 将 HTTP 状态设置为 403, 并返回 1。 ## is\_search\_engine 访问者是搜索引擎吗? ``` if(CGI::Info->new()->is_search_engine()) { # display generic information about yourself } else { # allow the user to pick and choose something to display } ``` 可以通过 IS\_SEARCH\_ENGINE 环境设置覆盖 ## browser\_type 返回 'web'、'search'、'robot' 和 'mobile' 之一。 ``` # Code to display a different web page for a browser, search engine and # smartphone use Template; use CGI::Info; my $info = CGI::Info->new(); my $dir = $info->rootdir() . '/templates/' . $info->browser_type(); my $filename = ref($self); $filename =~ s/::/\//g; $filename = "$dir/$filename.tmpl"; if((!-f $filename) || (!-r $filename)) { die "Can't open $filename"; } my $template = Template->new(); $template->process($filename, {}) || die $template->error(); ``` ## get\_cookie 返回 cookie 的值,如果未给出名称则返回 undef,或者请求的 cookie 不在 jar 中。 已弃用 - 请改用 cookie()。 ``` use CGI::Info; my $i = CGI::Info->new(); my $name = $i->get_cookie(cookie_name => 'name'); print "Your name is $name\n"; my $address = $i->get_cookie('address'); print "Your address is $address\n"; ``` ## cookie 返回 cookie 的值,如果未给出名称则返回 undef,或者请求的 cookie 不在 jar 中。 API 与 "param" 相同, 它将在未来取代 "get\_cookie" 方法。 ``` use CGI::Info; my $name = CGI::Info->new()->cookie('name'); print "Your name is $name\n"; ``` ### API 规范 #### 输入 ``` { cookie_name => { 'type' => 'string', 'min' => 1, 'matches' => qr/^[!#-'*+\-.\^_`|~0-9A-Za-z]+$/ # RFC6265 } } ``` #### 输出 Cookie 未设置:`undef` Cookie 已设置: ``` { type => 'string', optional => 1, matches => qr/ # RFC6265 ^ (?: "[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]*" # quoted | [\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]* # unquoted ) $ /x } ``` ## status($status) 设置或返回对象的状态, 200 表示 OK, 否则为 HTTP 错误代码 - $status 要设置或检索的可选整数值。 如果省略,则检索该值。 ## messages 返回对象已生成的消息,作为哈希数组的引用。 ``` my @messages; if(my $w = $info->messages()) { @messages = map { $_->{'message'} } @{$w}; } else { @messages = (); } print STDERR join(';', @messages), "\n"; ``` ## messages\_as\_string 返回对象已生成的消息,作为字符串。 ## cache($cache) 获取/设置内部缓存系统。 如果你看到这些错误消息,请使用此方法而不是将 cache 参数传递给 `new()`, "(in cleanup) Failed to get MD5\_CTX pointer"。 这是一个我无法弄清楚的晦涩问题, 但在 `new()` 之后调用它可以工作。 - $cache 可选的缓存对象。 未给出时, 返回当前的缓存对象。 ## set\_logger 设置将用于日志记录的类、数组、代码引用或文件。 有时在实例化类之前你不知道记录器是什么。 此函数解决了第 22 条军规(catch-22)的情况。 ## reset 重置类的类方法。 你应该在 FCGI 环境中实例化之前执行此操作, 但在其他地方不要这样做。 # 作者 Nigel Horne, `` # 错误 is\_tablet() 目前仅检测 iPad 和 Windows PC。Android 字符串 不区分平板电脑和智能手机。 params() 返回一个引用,这意味着调用例程可以更改哈希, 从而影响其他例程。 如果你不希望发生意外 事情,请在修改表之前制作本地副本。 # 另请参阅 - [测试仪表板](https://nigelhorne.github.io/CGI-Info/coverage/) - [Object::Configure](https://metacpan.org/pod/Object%3A%3AConfigure) - [HTTP::BrowserDetect](https://metacpan.org/pod/HTTP%3A%3ABrowserDetect) [https://github.com/mitchellkrogza/apache-ultimate-bad-bot-blocker](https://github.com/mitchellkrogza/apache-ultimate-bad-bot-blocker) # 仓库 [https://github.com/nigelhorne/CGI-Info](https://github.com/nigelhorne/CGI-Info) # 支持 此模块按“原样”提供,不提供任何保证。 请将任何错误或功能请求报告给 `bug-cgi-info at rt.cpan.org`, 或通过 Web 界面在 [http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CGI-Info](http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CGI-Info)。 我将收到通知,然后随着我进行更改,你将 自动收到有关你的 Bug 进度的通知。 你可以使用 perldoc 命令找到此模块的文档。 ``` perldoc CGI::Info ``` 你也可以在以下位置查找信息: - MetaCPAN [https://metacpan.org/dist/CGI-Info](https://metacpan.org/dist/CGI-Info) - RT: CPAN 的请求跟踪器 [https://rt.cpan.org/NoAuth/Bugs.html?Dist=CGI-Info](https://rt.cpan.org/NoAuth/Bugs.html?Dist=CGI-Info) - CPAN 测试人员矩阵 [http://matrix.cpantesters.org/?dist=CGI-Info](http://matrix.cpantesters.org/?dist=CGI-Info) - CPAN 测试人员依赖关系 [http://deps.cpantesters.org/?module=CGI::Info](http://deps.cpantesters.org/?module=CGI::Info) # 许可证和版权 版权所有 2010-2026 Nigel Horne。 使用受许可条款约束。 本软件的许可条款如下: - 个人单用户、单计算机使用:GPL2 - 所有其他用户(包括商业、慈善、教育、政府) 必须书面申请使用许可,致函上述电子邮件地址的 Nigel Horne。
标签:AppImage, CGI, CPAN, DNS解析, Perl, Syscall, WAF, Web应用防火墙, Web开发, 代码可移植性, 动态网页, 后端开发, 库文件, 开源项目, 环境变量, 系统信息, 网络安全, 脚本配置, 隐私保护