OWASP (Open Web Application Security Project) 是一个记录当前 web 应用所受威胁情况的项目。我一直都在关注他们的网站,从 2010,2013 和 2017 年的报告中我发现了一些相似之处,SQL 或其他类型的注入威胁都是高居榜首。
这是个心腹大患。
它会导致你破产,因此这个事情关乎存亡,你单位应该着力处理此类问题避免它的出现。
什么是注入?
所谓注入,就是数据没有经过过滤,将无法信任的内容直接写入了系统解释器,这种行为会导致对站点产生 SQL 注入,更糟糕的是,攻击者可能会获得对系统的全部权限。
举个例子:
看下面的恶意查询语句,它会将含有恶意行为的 SQL 语句放在 $name 变量里,然后允许用户通过 POST 的方式传递给 PHP 脚本,从而达到最终使用传入的恶意代码进行攻击的目的。
// 将恶意代码,DROP TABLE 写入 $name 变量 $name = "Mark';DROP TABLE users; -- ";\ $query = "SELECT * FROM users WHERE name='$name'";
经过 PHP 脚本解析,这会最终生成这样的 SQL 语句:
SELECT * FROM users WHERE name='Mark';DROP TABLE users; -- '
正如你猜的那样,上述语句会将整个 users 数据表从数据库里删除掉。
正如尤达说的:
这太危险了,是的,太危险了。
如何防止对 PHP 应用的恶意注入?
首先,其实并没有真的往数据库里注入什么东西,这种错误只是由于没有正确地将查询语句格式化。解决的方法很简单,只要正确地格式化 SQL 语句,或者是直接把查询语句和数据分开处理。
怎么做呢?用参数化查询对数据格式化,并使查询语句与数据分离。
使用参数化查询,可以确保程序远离注入风险。
例子如下:
$statement = $db->prepare('SELECT * FROM table WHERE id = ? and name = ? ');\ $statement->execute([1, "Mark"]);
除此之外,还有一种安全的做法,就是在项目中使用 ORM ( 对象关系映射)或者是查询构造器。
我要推荐的是著名的 PHP 框架 Laravel 也在用的 Eloquent。接下来,我会教你如何安装和使用,它可以帮助我们做好数据格式化的工作,从而有效避免注入危害。
安装 Eloquent
准备工作
请确保你已经安装了 PHP 和 Composer。
正式开始
最好在项目开始之初就安装 ORM。
假设我们想建一个博客应用,包含一个 posts 表和一个 users 表。
初始化配置
首先要做的是为程序创建 composer.json 文件。 你可以在终端上运行 composer init 并按照终端上的提示进行操作。
当他要求您来定义依赖关系的时候,写入 illuminate/database . 最后的输出应该和上面的图片中显示的一样。现在你就可以在项中通过运行 composer install 来安装相应的依赖了。
或者,如果你已经有了 composer.json 这个文件,你可以直接在终端输入 composer require illuminate/database 来安装相应的依赖。
现在我们需要在应用程序的根目录中创建 start.php 文件并把下面的代码粘贴到文件中。我会在下面解释他们的作用。
require "vendor/autoload.php"; //If you want the errors to be shown *是否显示错误 error_reporting(E_ALL); ini_set('display_errors', '1'); use Illuminate\Database\Capsule\Manager as Capsule; $capsule = new Capsule; $capsule->addConnection([ "driver" => "mysql", "host" =>"127.0.0.1", "database" => "test", "username" => "root", "password" => "root" ]); //Make this Capsule instance available globally. *要让 capsule 能在全局使用 $capsule->setAsGlobal(); // Setup the Eloquent ORM. $capsule->bootEloquent();
在第一行我们需要引入 vendor/autoload.php 文件。这样我们才能加载到 vendor 目录下的所有包。
然后我们引入 use Illuminate\Database\Capsule\Manager as Capsule 并起别名 ,这样子我们就能使用 eloquent 了。
接下来,我们创建一个 Capsule 对象并初始化我们的数据库连接, 如上 bootEloquent() 。
现在,很明显我们要做的第一件事就是创建名为 test 的数据库,请确保你在自己本地输入的是正确的用户名和密码.
Migrations / 数据迁移
使用 Eloquent 的一个最大的好处就是可以使用 migrations。
如果你不了解什么是 migrations,可以看下面的解释:
migration 是一种可以通过 PHP 代码创建数据表的方式。
在 migrations.php 文件中创建 migration:
require "start.php"; use Illuminate\Database\Capsule\Manager as Capsule; Capsule::schema()->create('users', function ($table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('password'); $table->timestamps(); }); Capsule::schema()->create('posts', function ($table) { $table->increments('id'); $table->string('title'); $table->text('body'); $table->integer('created_by')->unsigned(); $table->timestamps(); });
上面这段代码,通过 Capsule 类创建了两个数据表,一个是 users 表,另一个是 posts 表,并且分别为他们定义了字段名。
运行这个文件,如果你看到白屏,就说明 migrations 运行成功了,现在就可以打开数据库看看是否生成了这两个表。
Models
现在,唯一要做的就是创建对应数据表的 Model 类。
用了 Eloquent,你就可以在 Model 类里操作相应的数据表,执行查询语句了。
创建一个 Models 文件夹,然后在其中分别创建 User.php 和 Post.php 文件:
namespace Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 对应的数据表 * * @var string */ protected $table = "users"; /** * 允许插入的字段 * * @var array */ protected $fillable = [ 'name', 'email', 'password' ]; /** * 需要被隐藏的字段 * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; /* * 给 User 类添加方法 * */ public function posts() { return $this->hasMany(Post::class, 'created_by'); } } And namespace Models; use Illuminate\Database\Eloquent\Model; class Post extends Model { /** * 对应的数据表 * * @var string */ protected $table = "posts"; /** * 允许插入的字段 * * @var array */ protected $fillable = [ 'title', 'body', 'created_by' ]; } 在 composer.json 文件中加入如下代码,以确保上面创建的类文件能够被自动加载。 "autoload": { "classmap": [ "Models" // Folder where all your models are ] }
然后执行 composer dump-autoload。
通过 Eloquent 操作数据库
基本大功告成了。 测一下吧,在根目录创建 index.php 文件,添加如下代码:
require "start.php"; use Models\User; use Models\Post; User::create( [ 'name' => 'Mark Mike', 'email' => 'temp-email-1@mark.com', 'password' => '1234' ] ); Post::create( [ 'title' => 'New Blog Post', 'body' => 'New Blog Content', 'created_by' => 1 ] ); print_r(User::all()); print_r(Post::all()); print_r(User::find(1)->posts);
如你所见,用 Eloquent 操作数据库就是这么简单。除此之外,Eloquent 还提供了很多方法供你使用,而且很安全。
结语:
Eloquent 就像是给你的 SQL 查询加了一道安全层,它可以过滤掉我们在执行 SQL 查询时所犯的错误。如果你想用它,但是又不想安装 Laravel 框架,那么我想你已经从这篇文章中学到了该如何去做。这个优雅的 SQL 助手,将帮助你写出更干净且更安全的代码。
更多PHP相关知识,请访问PHP中文网!
Atas ialah kandungan terperinci 在你的 PHP 项目中单独使用 Laravel Eloquent 查询语句来避免 SQL 注入. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!