本文目录导读:

- 核心原则:入口文件只做三件事
- 极致精简版:单行启动器(以Laravel为例)
- 手动路由版:极简路由器
- 使用前端控制器模式(Front Controller)
- 安全加固:服务器级别隔离
- 进阶保护:入口文件自我防护(可选)
- 完整的保护示例
为PHP项目精简并保护入口文件(通常是index.php),核心思路是:将入口文件从“业务调度中心”变为“纯粹的启动器”,并利用服务器配置进行隔离。
以下是具体方案,按重要性排序。
核心原则:入口文件只做三件事
一个“干净”的入口文件应该只负责:
- 定义常量(如根目录路径)。
- 加载 Composer 自动加载器。
- 启动框架/应用内核(如 Laravel 的
$app->run())。
不要在入口文件里写业务逻辑、数据库查询、条件判断或HTML输出。
极致精简版:单行启动器(以Laravel为例)
现代框架通常已将入口文件精简到极致,看一个典型的Laravel入口文件:
<?php
// public/index.php
// 1. 自动加载
require __DIR__.'/../vendor/autoload.php';
// 2. 启动应用并返回响应
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
$kernel->terminate($request, $response);
精简点:
- 无业务逻辑
- 无全局变量污染
- 所有功能委托给框架内核
手动路由版:极简路由器
如果你没有使用框架,可以自己实现一个极简路由器,核心思想:入口文件不解析路由,只转发到路由器处理器。
入口文件 (index.php):
<?php
// 定义项目根目录
define('BASE_PATH', dirname(__DIR__));
// 加载自动加载和通用函数
require BASE_PATH . '/vendor/autoload.php';
require BASE_PATH . '/config/functions.php';
// 启动路由器(路由器本身可以是一个类)
$router = new App\Router();
$router->dispatch();
路由器文件 (src/Router.php):
<?php
namespace App;
class Router {
public function dispatch() {
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// 路由映射
$routes = require BASE_PATH . '/routes/web.php'; // 路由配置独立
// 匹配并执行控制器方法...
}
}
关键:入口文件只负责加载基础模块,启动路由器,之后所有逻辑都在 Router 类或控制器中处理。
使用前端控制器模式(Front Controller)
这是大多数框架采用的标准模式,所有请求都统一经过一个入口文件,但这个入口文件不解析任何路由,只负责创建应用实例。
<?php // index.php require __DIR__ . '/../bootstrap/app.php'; // app.php 会返回一个 Application 实例 $app->run();
保护手段:
- 入口文件只负责启动,攻击者无法通过修改入口文件来改变应用行为。
- 应用核心代码位于
bootstrap/或src/目录,不对外暴露。
安全加固:服务器级别隔离
即使入口文件再精简,如果服务器配置不当,依然存在风险,以下是必须做的:
1 禁止直接访问敏感目录
在 Nginx 中配置:
location ~* /(vendor|src|config|routes|database|tests)/ {
deny all;
return 404;
}
# 只允许 index.php 被访问
location / {
try_files $uri $uri/ /index.php?$query_string;
}
在 Apache 中(.htaccess 放在 public/ 目录):
# 禁止访问 /vendor/ 目录
RewriteRule ^vendor/ - [F,L]
RewriteRule ^src/ - [F,L]
RewriteRule ^config/ - [F,L]
# 将所有请求重定向到 index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
2 隐藏 PHP 版本信息
// 在入口文件或配置中加入
header_remove('X-Powered-By');
或在 php.ini 中设置:
expose_php = Off
3 使用单一入口目录结构
project/ ├── public/ # Web 服务器根目录,只放 index.php 和静态资源 │ ├── index.php # 入口文件 │ ├── css/ │ ├── js/ │ └── .htaccess # Apache 配置 ├── src/ # 业务代码 (禁止直接访问) ├── vendor/ # Composer 依赖 (禁止直接访问) ├── config/ # 配置文件 (禁止直接访问) └── ...
关键:Web 服务器根目录必须设为 public/,用户无法访问 src/、vendor/ 等目录。
进阶保护:入口文件自我防护(可选)
如果对安全要求极高,可以在入口文件开头添加简单的自我校验:
<?php
// 防止入口文件被直接访问(配合重定向使用)
if (php_sapi_name() !== 'cli' && !defined('ENTRY_POINT')) {
define('ENTRY_POINT', true);
}
// 防止恶意文件包含
$allowed_scripts = [
'/index.php',
'/vendor/autoload.php',
// ...
];
但请注意,过于复杂的自检逻辑会增加入口文件负担,背离“精简”初衷。建议以服务器配置为主要防护手段。
完整的保护示例
文件 public/index.php:
<?php
// 1. 定义根路径常量
define('BASE_PATH', dirname(__DIR__));
// 2. 加载 Composer 自动加载器
require BASE_PATH . '/vendor/autoload.php';
// 3. 加载环境配置
$dotenv = Dotenv\Dotenv::createImmutable(BASE_PATH);
$dotenv->load();
// 4. 启动应用
$app = require BASE_PATH . '/bootstrap/app.php';
$app->run();
文件 public/.htaccess (Apache):
<IfModule mod_rewrite.c>
RewriteEngine On
# 禁止访问 /../ 之外的任何目录
RewriteRule ^(vendor|src|config|routes|database|tests)/ - [F,L]
# 重定向所有请求到 index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
</IfModule>
# 防止目录列表
Options -Indexes
| 策略 | 作用 | 实现难度 |
|---|---|---|
| 入口文件只做启动 | 精简代码,降低攻击面 | 低,重构即可 |
| 前端控制器模式 | 统一请求处理,无业务逻辑 | 中,适合框架 |
| 服务器配置隔离 | 禁止访问敏感目录 | 必做 |
| 单一入口目录 | 物理隔离 public/ 与代码 | 必做 |
| 隐藏版本信息 | 降低针对性攻击 | 简单 |
一句话建议:入口文件越短越好,安全依赖服务器配置和框架架构,不依赖入口文件自身代码量。 一个20行的 index.php 比200行但安全配置缺失的入口文件要安全得多。