如果您尝试将 Phar 用于 Web 应用程序,并且只看到空白屏幕,如果您也启用了 Suhosin,则必须添加
suhosin.executor.include.whitelist="phar"
到 "/etc/php5/conf.d/suhosin.ini" 文件或您的 "php.ini" 文件。
完成后,一切正常。
Phar 归档在概念上类似于 Java JAR 归档,但它针对 PHP 应用程序的需求和灵活性进行了调整。Phar 归档用于将完整的 PHP 应用程序或库分发到单个文件中。Phar 归档应用程序的使用方式与任何其他 PHP 应用程序完全相同。
php coolapplication.phar
使用 Phar 归档库与使用任何其他 PHP 库相同。
<?php
include 'coollibrary.phar';
?>
phar
流包装器提供了 phar 扩展的核心功能,并在此处详细解释。phar 流包装器允许使用 PHP 的标准文件函数fopen()、opendir()以及其他可用于常规文件的函数来访问 phar 归档中的文件。 phar
流包装器支持对文件和目录的所有读/写操作。
<?php
include 'phar://coollibrary.phar/internal/file.php';
header('Content-type: image/jpeg');
// phars 可以通过完整路径或别名访问
echo file_get_contents('phar:///fullpath/to/coollibrary.phar/images/wow.jpg');
?>
Phar 类实现了用于访问文件和创建 phar 归档的高级功能。此处详细解释了 Phar 类。
<?php
try {
// 打开现有的 phar
$p = new Phar('coollibrary.phar', 0);
// Phar 扩展了 SPL 的 DirectoryIterator 类
foreach (new RecursiveIteratorIterator($p) as $file) {
// $file 是 PharFileInfo 类,并继承自 SplFileInfo
echo $file->getFileName() . "\n";
echo file_get_contents($file->getPathName()) . "\n"; // 显示内容;
}
if (isset($p['internal/file.php'])) {
var_dump($p['internal/file.php']->getMetadata());
}
// 创建新的 phar - php.ini 中的 phar.readonly 必须为 0
// 默认情况下,出于安全原因启用了 phar.readonly。
// 在生产服务器上,无需创建 Phars,
// 只需执行。
if (Phar::canWrite()) {
$p = new Phar('newphar.tar.phar', 0, 'newphar.tar.phar');
// 将其设为基于 tar 的 phar 归档,并使用 gzip 压缩进行压缩(.tar.gz)
$p = $p->convertToExecutable(Phar::TAR, Phar::GZ);
// 创建事务 - 在调用 stopBuffering() 之前,不会将任何内容写入 newphar.phar,尽管需要临时存储
$p->startBuffering();
// 添加 /path/to/project 中的所有文件,并在 phar 中使用前缀“project”保存
$p->buildFromIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/path/to/project')), '/path/to/');
// 通过数组访问 API 添加新文件
$p['file1.txt'] = 'Information';
$fp = fopen('hugefile.dat', 'rb');
// 从流中复制所有数据
$p['data/hugefile.dat'] = $fp;
if (Phar::canCompress(Phar::GZ)) {
$p['data/hugefile.dat']->compress(Phar::GZ);
}
$p['images/wow.jpg'] = file_get_contents('images/wow.jpg');
// 任何值都可以保存为文件特定的元数据
$p['images/wow.jpg']->setMetadata(array('mime-type' => 'image/jpeg'));
$p['index.php'] = file_get_contents('index.php');
$p->setMetadata(array('bootstrap' => 'index.php'));
// 将 phar 归档保存到磁盘
$p->stopBuffering();
}
} catch (Exception $e) {
echo '无法打开 Phar: ', $e;
}
?>
此外,可以使用任何支持的对称哈希算法(如果启用了 ext/hash,则为 MD5、SHA1、SHA256 和 SHA512)以及使用 OpenSSL 进行非对称公钥/私钥签名来验证 phar 文件内容。要利用 OpenSSL 签名,您需要生成公钥/私钥对,并使用私钥使用Phar::setSignatureAlgorithm()设置签名。此外,公钥可以使用此代码提取
<?php
$public = openssl_get_publickey(file_get_contents('private.pem'));
$pkey = '';
openssl_pkey_export($public, $pkey);
?>
/path/to/my.phar
,则公钥必须保存为 /path/to/my.phar.pubkey
,否则 Phar 将无法验证 OpenSSL 签名。
Phar 类还提供 3 个静态方法,Phar::webPhar()、Phar::mungServer() 和 Phar::interceptFileFuncs(),这些方法对于打包设计用于常规文件系统和基于 Web 的应用程序的 PHP 应用程序至关重要。Phar::webPhar() 实现了一个前端控制器,它将 HTTP 调用路由到 Phar 归档文件中的正确位置。Phar::mungServer() 用于修改 $_SERVER 数组的值,以欺骗处理这些值的应用程序。Phar::interceptFileFuncs() 指示 Phar 拦截对 fopen()、file_get_contents()、opendir() 和所有基于 stat 的函数(file_exists()、is_readable() 等)的调用,并将所有相对路径路由到 Phar 归档文件中的位置。
例如,打包流行的 phpMyAdmin 应用程序的版本以用作 Phar 归档文件只需要这个简单的脚本,然后修改用户/密码后,可以从 Web 服务器访问 phpMyAdmin.phar.tar.php
作为常规文件。
<?php
@unlink('phpMyAdmin.phar.tar.php');
copy('phpMyAdmin-2.11.3-english.tar.gz', 'phpMyAdmin.phar.tar.php');
$a = new Phar('phpMyAdmin.phar.tar.php');
$a->startBuffering();
$a["phpMyAdmin-2.11.3-english/config.inc.php"] = '<?php
/* Servers configuration */
$i = 0;
/* Server localhost (config:root) [1] */
$i++;
$cfg[\'Servers\'][$i][\'host\'] = \'localhost\';
$cfg[\'Servers\'][$i][\'extension\'] = \'mysqli\';
$cfg[\'Servers\'][$i][\'connect_type\'] = \'tcp\';
$cfg[\'Servers\'][$i][\'compress\'] = false;
$cfg[\'Servers\'][$i][\'auth_type\'] = \'config\';
$cfg[\'Servers\'][$i][\'user\'] = \'root\';
$cfg[\'Servers\'][$i][\'password\'] = \'\';
/* End of servers configuration */
if (strpos(PHP_OS, \'WIN\') !== false) {
$cfg[\'UploadDir\'] = getcwd();
} else {
$cfg[\'UploadDir\'] = \'/tmp/pharphpmyadmin\';
@mkdir(\'/tmp/pharphpmyadmin\');
@chmod(\'/tmp/pharphpmyadmin\', 0777);
}';
$a->setStub('<?php
Phar::interceptFileFuncs();
Phar::webPhar("phpMyAdmin.phar", "phpMyAdmin-2.11.3-english/index.php");
echo "phpMyAdmin is intended to be executed from a web browser\n";
exit -1;
__HALT_COMPILER();
');
$a->stopBuffering();
?>
如果您尝试将 Phar 用于 Web 应用程序,并且只看到空白屏幕,如果您也启用了 Suhosin,则必须添加
suhosin.executor.include.whitelist="phar"
到 "/etc/php5/conf.d/suhosin.ini" 文件或您的 "php.ini" 文件。
完成后,一切正常。
如果您要从浏览器运行 webPhar,例如 https://127.0.0.1/myphar.phar,那么您可能必须在您的 Web 服务器中将 .phar 扩展名与 PHP 关联以解释 PHP 代码。在 Apache 中,修改 httpd.conf 以包含
AddType application/x-httpd-php .php .phar
openssl 示例完全错误。公钥必须从证书中提取,而 openssl_pkey_export() 仅用于私钥。
可行的示例
<?php
$publicKey = openssl_get_publickey(file_get_contents('certificate.pem'));
$details = openssl_pkey_get_details($publicKey);
file_put_contents('my.phar.pubkey', $details['key']);
?>
无需赘述,如果使用者不针对有效的公钥指纹或证书进行检查,则 my.phar/.phar/signature.bin 的最佳和最强大的加密毫无用处,因为任何人都可以打开、读取、重新创建并使用新密钥签名新的存档。您这样做吗?仔细考虑一下。