PHP 项目中单独使用 Laravel Eloquent 查询语句来避免 SQL 注入
OWASP?(Open Web Application Security Project) 是一個(gè)記錄當(dāng)前 web 應(yīng)用所受威脅情況的項(xiàng)目。我一直都在關(guān)注他們的網(wǎng)站,從 2010,2013 和 2017 年的報(bào)告中我發(fā)現(xiàn)了一些相似之處,SQL 或其他類型的注入威脅都是高居榜首。
這是個(gè)心腹大患。
它會(huì)導(dǎo)致你破產(chǎn),因此這個(gè)事情關(guān)乎存亡,你單位應(yīng)該著力處理此類問(wèn)題避免它的出現(xiàn)。
什么是注入?
所謂注入,就是數(shù)據(jù)沒(méi)有經(jīng)過(guò)過(guò)濾,將無(wú)法信任的內(nèi)容直接寫(xiě)入了系統(tǒng)解釋器,這種行為會(huì)導(dǎo)致對(duì)站點(diǎn)產(chǎn)生SQL注入,更糟糕的是,攻擊者可能會(huì)獲得對(duì)系統(tǒng)的全部權(quán)限。
舉個(gè)例子:
看下面的惡意查詢語(yǔ)句,它會(huì)將含有惡意行為的SQL語(yǔ)句放在$name變量里,然后允許用戶通過(guò)POST的方式傳遞給PHP腳本,從而達(dá)到最終使用傳入的惡意代碼進(jìn)行攻擊的目的。
*//將惡意代碼, DROP TABLE寫(xiě)入name = "Mark';DROP TABLE users; -- ";
name'";`
經(jīng)過(guò)PHP腳本解析,這會(huì)最終生成這樣的SQL語(yǔ)句: SELECT * FROM users WHERE name='Mark';DROP TABLE users; -- '
正如你猜的那樣,上述語(yǔ)句會(huì)將整個(gè)users數(shù)據(jù)表從數(shù)據(jù)庫(kù)里刪除掉。
正如尤達(dá)說(shuō)的:
這太危險(xiǎn)了,是的,太危險(xiǎn)了。
如何防止對(duì) PHP 應(yīng)用的惡意注入?
首先,其實(shí)并沒(méi)有真的往數(shù)據(jù)庫(kù)里注入什么東西,這種錯(cuò)誤只是由于沒(méi)有正確地將查詢語(yǔ)句格式化。解決的方法很簡(jiǎn)單,只要正確地格式化 SQL 語(yǔ)句,或者是直接把查詢語(yǔ)句和數(shù)據(jù)分開(kāi)處理。
怎么做呢?用參數(shù)化查詢對(duì)數(shù)據(jù)格式化,并使查詢語(yǔ)句與數(shù)據(jù)分離。
使用參數(shù)化查詢,可以確保程序遠(yuǎn)離注入風(fēng)險(xiǎn)。
例子如下:
$statement = $db->prepare('SELECT * FROM table WHERE id = ? and name = ? ');\ $statement->execute([1, "Mark"]);
除此之外,還有一種安全的做法,就是在項(xiàng)目中使用 ORM ( 對(duì)象關(guān)系映射)或者是查詢構(gòu)造器。
我要推薦的是著名的 PHP 框架 Laravel 也在用的 Eloquent。接下來(lái),我會(huì)教你如何安裝和使用,它可以幫助我們做好數(shù)據(jù)格式化的工作,從而有效避免注入危害。
更多關(guān)于 Eloquent 知識(shí)可以參考?laravel docs.
安裝 Eloquent
準(zhǔn)備工作
請(qǐng)確保你已經(jīng)安裝了 PHP 和?Composer。
正式開(kāi)始
最好在項(xiàng)目開(kāi)始之初就安裝 ORM。
假設(shè)我們想建一個(gè)博客應(yīng)用,包含一個(gè) posts 表和一個(gè) users 表。
初始化配置
首先要做的是為程序創(chuàng)建 composer.json 文件。 你可以在終端上運(yùn)行 composer init ?并按照終端上的提示進(jìn)行操作。
當(dāng)他要求您來(lái)定義依賴關(guān)系的時(shí)候, 寫(xiě)入?illuminate/database?. 最后的輸出應(yīng)該和上面的圖片中顯示的一樣。現(xiàn)在你就可以在項(xiàng)中通過(guò)運(yùn)行 ?composer install? 來(lái)安裝相應(yīng)的依賴了。
或者,如果你已經(jīng)有了?composer.json 這個(gè)文件, 你可以直接在終端輸入 ?composer require illuminate/database 來(lái)安裝相應(yīng)的依賴。
現(xiàn)在我們需要在應(yīng)用程序的根目錄中創(chuàng)建 ?start.php?文件并把下面的代碼粘貼到文件中。我會(huì)在下面解釋他們的作用。
require "vendor/autoload.php"; //If you want the errors to be shown *是否顯示錯(cuò)誤 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(); 復(fù)制代碼在第一行我們需要引入?vendor/autoload.php 文件。這樣我們才能加載到 vendor 目錄下的所有包。
然后我們引入 use Illuminate\Database\Capsule\Manager as Capsule 并起別名 ,這樣子我們就能使用 eloquent 了。
接下來(lái), 我們創(chuàng)建一個(gè) Capsule 對(duì)象并初始化我們的數(shù)據(jù)庫(kù)連接, 如上 ?bootEloquent()?。
現(xiàn)在, 很明顯我們要做的第一件事就是創(chuàng)建名為 test?的數(shù)據(jù)庫(kù),請(qǐng)確保你在自己本地輸入的是正確的用戶名和密碼.
Migrations / 數(shù)據(jù)遷移
使用 Eloquent 的一個(gè)最大的好處就是可以使用 migrations。
如果你不了解什么是 migrations,可以看下面的解釋:
migration 是一種可以通過(guò) PHP 代碼創(chuàng)建數(shù)據(jù)表的方式。
在 migrations.php 文件中創(chuàng)建 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(); }); 復(fù)制代碼上面這段代碼,通過(guò) Capsule 類創(chuàng)建了兩個(gè)數(shù)據(jù)表,一個(gè)是 users 表,另一個(gè)是 posts 表,并且分別為他們定義了字段名。
運(yùn)行這個(gè)文件,如果你看到白屏,就說(shuō)明 migrations 運(yùn)行成功了,現(xiàn)在就可以打開(kāi)數(shù)據(jù)庫(kù)看看是否生成了這兩個(gè)表。
Models
現(xiàn)在,唯一要做的就是創(chuàng)建對(duì)應(yīng)數(shù)據(jù)表的 Model 類。
用了 Eloquent,你就可以在 Model 類里操作相應(yīng)的數(shù)據(jù)表,執(zhí)行查詢語(yǔ)句了。
創(chuàng)建一個(gè) Models 文件夾,然后在其中分別創(chuàng)建 User.php 和 Post.php 文件:
namespace Models; use Illuminate\Database\Eloquent\Model; class User extends Model {/*** 對(duì)應(yīng)的數(shù)據(jù)表** @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');} } 復(fù)制代碼And
namespace Models; use Illuminate\Database\Eloquent\Model; class Post extends Model {/*** 對(duì)應(yīng)的數(shù)據(jù)表** @var string*/protected $table = "posts";/*** 允許插入的字段** @var array*/protected $fillable = ['title', 'body', 'created_by'];} 復(fù)制代碼在 composer.json 文件中加入如下代碼,以確保上面創(chuàng)建的類文件能夠被自動(dòng)加載。
"autoload": {"classmap": ["Models" // Folder where all your models are] } 復(fù)制代碼然后執(zhí)行 composer dump-autoload。
通過(guò) Eloquent 操作數(shù)據(jù)庫(kù)
基本大功告成了。 測(cè)一下吧,在根目錄創(chuàng)建 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); 復(fù)制代碼如你所見(jiàn),用 Eloquent 操作數(shù)據(jù)庫(kù)就是這么簡(jiǎn)單。除此之外,Eloquent 還提供了很多方法供你使用,而且很安全。
結(jié)語(yǔ):
Eloquent 就像是給你的 SQL 查詢加了一道安全層,它可以過(guò)濾掉我們?cè)趫?zhí)行 SQL 查詢時(shí)所犯的錯(cuò)誤。如果你想用它,但是又不想安裝 Laravel 框架,那么我想你已經(jīng)從這篇文章中學(xué)到了該如何去做。這個(gè)優(yōu)雅的 SQL 助手,將幫助你寫(xiě)出更干凈且更安全的代碼。
文章轉(zhuǎn)自:learnku.com/php/t/25962
更多文章:learnku.com/php/c/trans…
轉(zhuǎn)載于:https://juejin.im/post/5c984181f265da610a56f4a7
總結(jié)
以上是生活随笔為你收集整理的PHP 项目中单独使用 Laravel Eloquent 查询语句来避免 SQL 注入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Node.js之readline模块的使
- 下一篇: Kubernetes日志分析利器:Ela