资讯专栏INFORMATION COLUMN

PHP 项目中多带带使用 Laravel Eloquent 查询语句来避免 SQL 注入

dayday_up / 3235人阅读

摘要:是一个记录当前应用所受威胁情况的项目。怎么做呢用参数化查询对数据格式化,并使查询语句与数据分离。使用参数化查询,可以确保程序远离注入风险。例子如下除此之外,还有一种安全的做法,就是在项目中使用对象关系映射或者是查询构造器。

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 知识可以参考 laravel docs.

安装 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 IlluminateDatabaseCapsuleManager 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 IlluminateDatabaseCapsuleManager as Capsule 并起别名 ,这样子我们就能使用 eloquent 了。

接下来, 我们创建一个 Capsule 对象并初始化我们的数据库连接, 如上  bootEloquent() 。

现在, 很明显我们要做的第一件事就是创建名为 test 的数据库,请确保你在自己本地输入的是正确的用户名和密码.

Migrations / 数据迁移

使用 Eloquent 的一个最大的好处就是可以使用 migrations。

如果你不了解什么是 migrations,可以看下面的解释:

migration 是一种可以通过 PHP 代码创建数据表的方式。

migrations.php 文件中创建 migration:

require "start.php";
use IlluminateDatabaseCapsuleManager 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.phpPost.php 文件:

namespace Models;
use IlluminateDatabaseEloquentModel;
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 IlluminateDatabaseEloquentModel;
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 ModelsUser;
use ModelsPost;
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 助手,将帮助你写出更干净且更安全的代码。

文章转自:https://learnku.com/php/t/25962 

更多文章:https://learnku.com/php/c/tra...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/31079.html

相关文章

  • Laravel核心解读--Database(一)基础介绍

    摘要:第三步注册工厂启动数据库服务数据库服务的启动主要设置的连接分析器,让能够用服务连接数据库。 在我们学习和使用一个开发框架时,无论使用什么框架,如何连接数据库、对数据库进行增删改查都是学习的重点,在Laravel中我们可以通过两种方式与数据库进行交互: DB, DB是与PHP底层的PDO直接进行交互的,通过查询构建器提供了一个方便的接口来创建及运行数据库查询语句。 Eloquent...

    reclay 评论0 收藏0
  • Laravel 的 ORM 返回的数据类型小结

    摘要:一简介的数据库查询构造器提供了一个方便流畅的接口,用来创建及运行数据库查询语句。的查询构造器使用参数绑定,来保护你的应用程序免受注入的攻击。和返回的是影响行数,即失败为,成功为删除行数。 相信很多人在学习 Laravel 时,会对 ORM 返回的数据类型产生混淆,如返回集合,模或者整数类型,下面将对增删改查操作进行一个小结。 一、简介 Laravel 的数据库查询构造器提供了一个方便、...

    LeviDing 评论0 收藏0
  • Laravel Eloquent中的 懒加载VS即时加载

    摘要:在本文中,我们将了解中的懒加载和即时加载以及它如何在后台运行。现在所有的房屋数据和在关系表中的数据都同时加载出来了,查询的语句的是使用即时加载时仅执行个查询。总结现在你理解了这个过程,希望它能帮助你理解懒加载和即时加载的用法和基本原理。 Laravel中的Eloquent(ORM)的工作方式很令人惊讶,并提供访问数据库的非常简单的方法。在本文中,我们将了解Laravel Eloquen...

    Keven 评论0 收藏0
  • Laravel 学习笔记之 Query Builder 源码解析(下)

    摘要:,看下源码返回很容易知道返回值是,然后将该值存储在变量中,这时。看下的源码去除掉字符后为返回从源码中可知道返回值为,这时。 说明:本文主要学习下Query Builder编译Fluent Api为SQL的细节和执行SQL的过程。实际上,上一篇聊到了IlluminateDatabaseQueryBuilder这个非常重要的类,这个类含有三个主要的武器:MySqlConnection, M...

    qpal 评论0 收藏0
  • Laravel 的十八个最佳实践

    摘要:本文翻译改编自的十八个最佳实践这篇文章并不是什么由改编的原则模式等。只是为了让你注意你在现实生活的项目中最常忽略的内容。单一职责原则正在帮助你避免重复。当然,这也包括了模板的范围等。此外,也拥有很棒的内置工具,比如软删除事件范围等。 showImg(https://segmentfault.com/img/remote/1460000015166532); 本文翻译改编自 Larave...

    gitmilk 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<