PHP如何创建只读表_PHP只读表设置用途【安全】

9次阅读

真正的只读安全必须通过数据库用户权限实现,即创建仅具select权限的账号并用于php连接;PHP层的只读设置(如READ ONLY、sql关键词拦截、ORM配置)仅为辅助手段,无法替代DB权限控制。

PHP如何创建只读表_PHP只读表设置用途【安全】

PHP 本身不直接“创建只读表”,数据库的只读属性由底层 DBMS(如 mysqlpostgresql)控制;PHP 只能通过连接权限、SQL 语句或 ORM 配置间接实现只读约束。强行在 PHP 层模拟只读(比如拦截 INSERT/UPDATE)不可靠,容易被绕过。

MySQL 用户级只读权限设置(最有效)

真正安全的只读,必须从数据库用户权限入手。用具有 SELECT 权限但无 INSERTUPDATEdeleteDROPALTER 权限的账号连接数据库。

  • 创建只读用户:
    CREATE USER 'app_ro'@'%' IDENTIFIED BY 'strong_password'; GRANT SELECT ON `mydb`.* TO 'app_ro'@'%'; FLUSH PRIVILEGES;
  • PHP 中使用该账号连接:
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'app_ro', 'strong_password');
  • 一旦执行写操作,MySQL 直接报错:SQLSTATE[42000]: Syntax Error or access rule violation: 1142 INSERT command denied to user...
  • 注意:不要给 app_ro 赋予 USAGE 或全局权限;SELECT 必须显式指定库/表范围,避免 GRANT SELECT ON *.*

PHP 连接层强制只读(辅助手段)

可在 PDO 构造后立即执行 SET session TRANSACTION READ ONLY(MySQL 5.6+),或设连接参数 PDO::ATTR_EMULATE_PREPARES => false 防止预处理语句绕过权限检查。

  • READ ONLY 会拒绝所有写操作(包括 CREATE TEMPORARY table),但前提是用户已有 READ_ONLY 全局变量修改权限——通常只给管理员,所以更推荐用用户权限控制
  • 若必须用 PHP 控制,可封装一个只读 PDO 类,在 exec() / prepare() 前校验 SQL 是否含 INSERTUPDATE 等关键词——但这只是防御性检查,不能替代 DB 权限
  • 避免使用 mysqli_real_escape_string() 后拼接 SQL,这种场景下关键词检测极易被绕过

laravel/Eloquent 中启用只读连接

框架可通过配置分离读写连接,或强制某模型只读。这不是数据库级防护,但能降低误操作风险。

立即学习PHP免费学习笔记(深入)”;

  • config/database.php 中配置读写分离:
    'mysql' => [     'read' => ['host' => ['192.168.1.10']],     'write' => ['host' => ['192.168.1.11']],     // ...其他配置 ]
  • 在 Eloquent 模型中禁用写操作:
    class Report extends Model {     public $timestamps = false;     protected $fillable = [];     public static function boot()     {         parent::boot();         static::creating(function () { return false; });         static::updating(function () { return false; });         static::deleting(function () { return false; });     } }
  • 注意:boot() 钩子可被绕过(如直接调用 DB::table()->update()),仅适用于业务逻辑层防护

真正的只读安全,核心在于数据库用户的最小权限原则。PHP 层的任何“只读开关”都只是补充,不是防线。最容易被忽略的是:开发环境常共用 root 账号,导致权限策略在测试阶段完全失效;上线前务必验证生产数据库账号是否真的只有 SELECT 权限,并用实际写操作触发一次报错来确认。

text=ZqhQzanResources