PHP 項(xiàng)目中單獨(dú)使用 Laravel Eloquent 查詢語句來避免 SQL 注入

file

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è)心腹大患浆竭。

它會導(dǎo)致你破產(chǎn)浸须,因此這個(gè)事情關(guān)乎存亡,你單位應(yīng)該著力處理此類問題避免它的出現(xiàn)邦泄。

什么是注入?

所謂注入羽戒,就是數(shù)據(jù)沒有經(jīng)過過濾,將無法信任的內(nèi)容直接寫入了系統(tǒng)解釋器虎韵,這種行為會導(dǎo)致對站點(diǎn)產(chǎn)生SQL注入易稠,更糟糕的是,攻擊者可能會獲得對系統(tǒng)的全部權(quán)限包蓝。

舉個(gè)例子:

看下面的惡意查詢語句驶社,它會將含有惡意行為的SQL語句放在$name變量里,然后允許用戶通過POST的方式傳遞給PHP腳本测萎,從而達(dá)到最終使用傳入的惡意代碼進(jìn)行攻擊的目的亡电。

*//將惡意代碼, DROP TABLE寫入name變量* `name = "Mark';DROP TABLE users; -- ";
query = "SELECT * FROM users WHERE name='name'";`

經(jīng)過PHP腳本解析,這會最終生成這樣的SQL語句:
SELECT * FROM users WHERE name='Mark';DROP TABLE users; -- '

正如你猜的那樣硅瞧,上述語句會將整個(gè)users數(shù)據(jù)表從數(shù)據(jù)庫里刪除掉份乒。

正如尤達(dá)說的:

這太危險(xiǎn)了,是的腕唧,太危險(xiǎn)了或辖。

如何防止對 PHP 應(yīng)用的惡意注入?

首先,其實(shí)并沒有真的往數(shù)據(jù)庫里注入什么東西枣接,這種錯(cuò)誤只是由于沒有正確地將查詢語句格式化颂暇。解決的方法很簡單,只要正確地格式化 SQL 語句但惶,或者是直接把查詢語句和數(shù)據(jù)分開處理耳鸯。

怎么做呢?用參數(shù)化查詢對數(shù)據(jù)格式化膀曾,并使查詢語句與數(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 ( 對象關(guān)系映射)或者是查詢構(gòu)造器碉钠。

我要推薦的是著名的 PHP 框架 Laravel 也在用的 Eloquent纲缓。接下來,我會教你如何安裝和使用喊废,它可以幫助我們做好數(shù)據(jù)格式化的工作祝高,從而有效避免注入危害。

更多關(guān)于 Eloquent 知識可以參考 laravel docs.

安裝 Eloquent

準(zhǔn)備工作

請確保你已經(jīng)安裝了 PHP 和 Composer污筷。

正式開始

最好在項(xiàng)目開始之初就安裝 ORM工闺。

假設(shè)我們想建一個(gè)博客應(yīng)用,包含一個(gè) posts 表和一個(gè) users 表瓣蛀。

初始化配置

首先要做的是為程序創(chuàng)建 composer.json 文件陆蟆。 你可以在終端上運(yùn)行 composer init 并按照終端上的提示進(jìn)行操作。

eloquent composer setup screenshot

當(dāng)他要求您來定義依賴關(guān)系的時(shí)候, 寫入 illuminate/database . 最后的輸出應(yīng)該和上面的圖片中顯示的一樣⊥镌觯現(xiàn)在你就可以在項(xiàng)中通過運(yùn)行 composer install 來安裝相應(yīng)的依賴了叠殷。

或者,如果你已經(jīng)有了 composer.json 這個(gè)文件, 你可以直接在終端輸入 composer require illuminate/database 來安裝相應(yīng)的依賴诈皿。

現(xiàn)在我們需要在應(yīng)用程序的根目錄中創(chuàng)建 start.php 文件并把下面的代碼粘貼到文件中林束。我會在下面解釋他們的作用。

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();

在第一行我們需要引入 vendor/autoload.php 文件稽亏。這樣我們才能加載到 vendor 目錄下的所有包壶冒。

然后我們引入 use Illuminate\Database\Capsule\Manager as Capsule 并起別名 ,這樣子我們就能使用 eloquent 了截歉。

接下來, 我們創(chuàng)建一個(gè) Capsule 對象并初始化我們的數(shù)據(jù)庫連接胖腾, 如上 bootEloquent()

現(xiàn)在, 很明顯我們要做的第一件事就是創(chuàng)建名為 test 的數(shù)據(jù)庫瘪松,請確保你在自己本地輸入的是正確的用戶名和密碼.

Migrations / 數(shù)據(jù)遷移

使用 Eloquent 的一個(gè)最大的好處就是可以使用 migrations咸作。

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

migration 是一種可以通過 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();
});

上面這段代碼性宏,通過 Capsule 類創(chuàng)建了兩個(gè)數(shù)據(jù)表,一個(gè)是 users 表状飞,另一個(gè)是 posts 表毫胜,并且分別為他們定義了字段名。

運(yùn)行這個(gè)文件诬辈,如果你看到白屏酵使,就說明 migrations 運(yùn)行成功了,現(xiàn)在就可以打開數(shù)據(jù)庫看看是否生成了這兩個(gè)表焙糟。

php myadmin models example

Models

現(xiàn)在口渔,唯一要做的就是創(chuàng)建對應(yīng)數(shù)據(jù)表的 Model 類。

用了 Eloquent穿撮,你就可以在 Model 類里操作相應(yīng)的數(shù)據(jù)表缺脉,執(zhí)行查詢語句了痪欲。

創(chuàng)建一個(gè) Models 文件夾,然后在其中分別創(chuàng)建 User.phpPost.php 文件:

namespace Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
   /**
    * 對應(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');
    }
}

And

namespace Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
   /**
    * 對應(yīng)的數(shù)據(jù)表
    *
    * @var string
    */
    protected $table = "posts";
  /**
   * 允許插入的字段
   *
   * @var array
   */
   protected $fillable = [
       'title', 'body', 'created_by'
   ];
 }

composer.json 文件中加入如下代碼攻礼,以確保上面創(chuàng)建的類文件能夠被自動(dòng)加載业踢。

"autoload": {
    "classmap": [
        "Models" // Folder where all your models are
     ]
}

然后執(zhí)行 composer dump-autoload

通過 Eloquent 操作數(shù)據(jù)庫

基本大功告成了礁扮。 測一下吧知举,在根目錄創(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);

如你所見太伊,用 Eloquent 操作數(shù)據(jù)庫就是這么簡單雇锡。除此之外,Eloquent 還提供了很多方法供你使用僚焦,而且很安全锰提。

結(jié)語:

Eloquent 就像是給你的 SQL 查詢加了一道安全層,它可以過濾掉我們在執(zhí)行 SQL 查詢時(shí)所犯的錯(cuò)誤芳悲。如果你想用它欲账,但是又不想安裝 Laravel 框架,那么我想你已經(jīng)從這篇文章中學(xué)到了該如何去做芭概。這個(gè)優(yōu)雅的 SQL 助手赛不,將幫助你寫出更干凈且更安全的代碼。

文章轉(zhuǎn)自:https://learnku.com/php/t/25962

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末罢洲,一起剝皮案震驚了整個(gè)濱河市踢故,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惹苗,老刑警劉巖殿较,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異桩蓉,居然都是意外死亡淋纲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門院究,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洽瞬,“玉大人,你說我怎么就攤上這事业汰』锴裕” “怎么了?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵样漆,是天一觀的道長为障。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么鳍怨? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任呻右,我火速辦了婚禮,結(jié)果婚禮上鞋喇,老公的妹妹穿的比我還像新娘声滥。我一直安慰自己,他們只是感情好确徙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著执桌,像睡著了一般鄙皇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仰挣,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天伴逸,我揣著相機(jī)與錄音,去河邊找鬼膘壶。 笑死错蝴,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的颓芭。 我是一名探鬼主播顷锰,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼亡问!你這毒婦竟也來了官紫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤州藕,失蹤者是張志新(化名)和其女友劉穎束世,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體床玻,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毁涉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锈死。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贫堰。...
    茶點(diǎn)故事閱讀 38,625評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖待牵,靈堂內(nèi)的尸體忽然破棺而出严嗜,到底是詐尸還是另有隱情,我是刑警寧澤洲敢,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布漫玄,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏睦优。R本人自食惡果不足惜渗常,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望汗盘。 院中可真熱鬧皱碘,春花似錦、人聲如沸隐孽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽菱阵。三九已至踢俄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晴及,已是汗流浹背都办。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虑稼,地道東北人琳钉。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像蛛倦,于是被迫代替她去往敵國和親歌懒。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容