编程

如何延长老版PHP应用的生命周期

592 2023-02-04 09:05:19

PHP正在稳步发展。每年都会有一个主要的新版本,其中包含新功能、性能改进、相当多的弃用,甚至语法更改。PHP核心开发人员维护两个最新的PHP版本,其中包括活动的bug修复和安全修复,然后是安全修复。这实际上意味着每个主要的PHP版本最多支持三年,现有的PHP应用程序就要被迫升级。

虽然更新现有的PHP应用程序是理想和推荐的方法,但不可避免的是,有些应用程序/网站无法证明进行更新所需的人力、政治和财务成本是合理的。对于运行在PHP5系列或PHP7系列上的遗留PHP应用程序,情况尤其如此。例如,WordPress.org报告称,只有16%的WordPress站点运行在PHP核心开发人员支持的PHP版本上。

更新PHP应用程序以使其与最新的PHP版本兼容是非常困难的。有一些无需修改或只需少量修改,也有一些几乎需要完全重写。十多年前开发的PHP应用程序构成了最大的挑战,因为它们倾向于使用不再受支持、没有类型支持且通常也没有自动测试来验证更改的PHP扩展。

Rector等工具可以自动完成一些必要的更改(如果不是大多数的话),但非常旧的PHP版本往往需要大量的手动代码更新。

在某些情况下,升级的成本所要付出的努力和费用是不值得的。其中一些示例包括仅在专用网络中使用的内部应用程序、计划重写的应用程序,以及原始开发人员不再在公司工作的应用程序。实际上,这些应用程序可能永远不会更新;最终只会被替换掉。

由于PHP版本的官方更新时间只有三年,这可能会使应用程序容易受到安全漏洞的影响,而这些安全漏洞通常也会影响这些未维护的PHP版本。PHP平台即产品(PAAS)产品和共享托管提供商也强制更新到最新的PHP版本,这可能会使应用程序在新的PHP版本上崩溃。

本文讨论了在安全的PHP环境中运行遗留PHP应用程序的策略,以及额外的安全预防措施和维护,从而延长所述PHP应用程序寿命。

PHP应用程序越是锁定在PHP版本中,更新速度就越快。然而,与更新一个已有几十年历史的PHP应用程序相比,在旧应用程序被替换之前,再从旧应用程序中挤出几年时间有时更现实可行。

共享主机和平台到专用服务器

大多数共享和托管托管平台以及PHP PaaS 产品通常只提供当前的PHP版本,但从长远来看不支持旧的PHP版本。这是绝对有意义的,因为旧的PHP版本未维护,如果发现影响这些未维护的PHP版本的漏洞,可能会危及其服务器的安全。

如果托管提供商/PaaS提供商不再支持所需的PHP版本,那么寻找支持多种PHP版本的提供商可能是有意义的。

CloudLinux是共享/托管托管提供商在其服务器上使用的商业操作系统之一,这些提供商可能会启用CloudLinux的硬化PHP功能。硬化php是CloudLinux中的一个特性,即使在官方php.net团队将php版本标记为EOL之后,CloudLinux后台端口也会修复该特性。

另一种方法是维护私有服务器/云服务器并自行配置。维护VPS/Cloud服务器会带来维护负担,但现在大多数操作系统都具有正常的默认值、自动更新等功能,以减轻部分负担。但是,这种服务器维护可能不适合每个人。

Debian LTS、Ubuntu LTS、Rocky Linux和RHEL是一些基于Linux的操作系统,它们在默认存储库中提供PHP。他们不会从上游接收错误修复,但安全修复会在适用的情况下进行反向移植。

例如,Ubuntu 20.04 LTS在其默认存储库中包含PHP 7.4.3。Ubuntu 20.04 LTS将在2025年之前接收硬件和维护更新。PHP 7.4目前被官方PHP.net团队标记为“生命终结”,但Ubuntu 20.04背后的开发人员将任何安全补丁移植到存储库中可用的PHP版本。任何非安全性错误修复都不会被反向移植。这本质上意味着Ubuntu 20.04的PHP版本将保持为PHP 7.4.3,但应用了所有安全修复。Ubuntu的付费(五台个人电脑免费)Ubuntu Pro产品将其延长了五年,这意味着可以在2030年之前安全运行PHP 7.4应用程序。

Web服务器集成

PHP与Apache、Nginx、Litespeed、Caddy等web服务器集成。当运行遗留PHP应用程序时,建议切换到PHP-fpm作为服务器API。例如,Apache支持将PHP作为Apache模块运行,这阻碍了在应用程序必须在较旧的PHP版本上运行的情况下升级Apache版本的能力。

Nginx和Caddy只与php-fpm集成,因此不需要对它们进行任何更改。

PHP还有一个内置服务器。生产服务器不太可能使用它,但请确保使用完全成熟的web服务器来在PHP和web服务器之间添加分隔。

容器化PHP

当运行完整的LTS操作系统(如Ubuntu LTS)不可行时,另一种方法是使用容器来运行所需的PHP版本。

对于容器,除非明确允许,否则文件系统和网络的其余部分将保持完整。PHP-FPM进程可以在一个容器内运行,只需要最小的文件系统访问(允许会话存储、临时文件、文件上载等)、FPM端口(用于web服务器集成)和数据库端口,但其他所有内容都保留在容器内。

PECL扩展替换件

即使操作系统或第三方存储库提供了PHP更新,它们也不太可能为EOL PHP扩展提供安全更新。

  • 与外部服务(如SSH、FTP、电子邮件、LDAP等)连接的PECL扩展最好使用用户端PHP实现。
  • 提供加密操作的扩展(例如mcrypt和openssl)最好用Sodium或其用户端PHP polyfills等较新的扩展替换。
  • PDF库(如DomPDF)可以用无头浏览器或命令行工具(如wkhtmltopdf)代替。

图像生成扩展(如Imagick和GD)可以替换为提供图像处理的CDN。

Composer LTS

Composer,PHP的依赖关系管理器最近提高了最低PHP版本要求。然而,Composer 2.2是Composer 2的LTS版本,应该至少在2023年底支持该版本。

Composer在升级最低要求的PHP版本时相当保守,因此即使在较旧的PHP版本上也应该相对无故障。

LTS框架、库和本地分叉

PHP框架和库(如Laravel和Nette)往往是快速更新的框架,而Symfony和Slim则更为保守。

  • 虽然Laravel以前提供的LTS版本提供了五年的安全更新,但最近的Laravel版本只提供了一年的主动支持,然后是一年的安全修复,因此可能需要手动移植安全更新。
  • 最近的Drupal版本(如Drupal 10)需要最新的PHP版本。Drupal 7目前仍在获得支持,但有一些免费的商业Drupal LTS项目,即使在正式达到EOL之后,也可以提供协调的安全版本。对于Drupal 7,还有BackDrop CMS,它提供了一个简单的升级路径。
  • WordPress试图保持与旧PHP版本的兼容性,因此即使在旧PHP版本上也可以更新到WordPress。

Symfony(及其组件)为LTS版本提供至少三年的安全更新。

当PHP库/框架放弃了PHP应用程序所依赖的版本时,PHP应用程序的维护人员就可以在进行存储库和后端安全更新时进行分叉。将这项工作作为公共项目进行共享,可以为其他人维护其他LTS包所付出的努力付出代价。对于私有包,本地克隆的存储库或私有Composer存储库可以使Composer集成工作。

PHP