在某些應用程序中,不暴露 ID 可以避免別人輕易獲悉你數據庫里模型的數量。
譯者注:隱藏 ID 也可有效防止用戶惡意遍歷網站的內容。
嘿, 想象一下,在我的 Podcast 應用程序中,我設置了一個默認 id 在 laravel 的 Podcast 模型中,它是一個整數,每次插入一行時都會自動增加一個,因此表中的第47個 Podcast 的 id 為47。 然后我在我的網站內聲稱:“這個 Podcast 應用程序擁有數百萬個播客,所以千萬不要錯過!”,在看到最新播客 ID 時很容易被揭穿:
https://podcast.app/podcasts/47
在不需要重新連接應用程序中的所有內容的情況下隱藏ID,并且希望不被識破? 好的,有一種方法。
設置數據庫
有些數據庫可以配置為在插入新行時將 UUID 設置為主鍵。你應該在正在使用的 RDBMS 上檢查這一點,因為每個 RDBMS 的實現都有所不同。
你還可以告訴應用程序在使用 創建 Eloqument 事件新紀錄時設置默認 UUID ,但這將使你在任何情況下都得使用 Eloqument 。如果你直接向數據庫中插入一條記錄,你可能會得到一個錯誤——這也是我喜歡在數據庫中設置自動 UUID 而不是應用程序的原因之一,它不應該依賴于任何東西,因為這是數據庫行為。
總之,你應該像這樣使用 Laravel 設置你的數據庫:
<?php use IlluminateSupportFacadesSchema; use IlluminateDatabaseSchemaBlueprint; use IlluminateDatabaseMigrationsMigration; class CreatePodcastTable extends Migration { /** * 運行數據庫遷移 * * @return void */ public function up() { Schema::create('podcast', function (Blueprint $table) { $table->bigIncrements('id'); $table->uuid('uuid')->index(); $table->string('filename'); $table->string('path'); $table->string('service'); $table->string('format', 4); $table->unsginedTinyInteger('quality', 4); $table->timestamps(); $table->timestamps(); $table->softDeletes(); }); } /** * 回滾數據庫遷移 * * @return void */ public function down() { Schema::dropIfExists('podcast'); } }
正如你看到的,我們增加了 $table->uuid(‘uuid’)->index() 。這段代碼告訴 Laravel 去使用 UUID 這一列(如果支持,或者使用字符串列),并在這一列上創建一個索引,這樣就可以通過 UUID 快速檢索行,就像有人訪問這個 URL 時所做的那樣:
https://podcast.app/podcast/535c4cdf-70a0-4615-82f2-443e95c86aec
你可能會爭辯說 另外一個索引會妨礙插入操作,但是這是一個權衡。
現在,問題在于控制器和模型。
將模型連接至 UUID
你不需要在模型中做任何事,除了兩件事:將 ID 從序列化中隱藏,并允許模型使用 UUID 進行「 URL 路由」。
<?php namespace App; use IlluminateDatabaseEloquentModel; class Podcast extends Model { /** * 數組中隱藏的屬性 * * @var array */ protected $hidden = [ 'id' ]; /** * 獲取模型的路由鍵 * * @return string */ public function getRouteKeyName() { return 'uuid'; } // ……其余的模型代碼 }
要隱藏 ID ,我們可以將 id 列添加至隱藏屬性數組中。當模型被序列化時,比如轉換為數組或 JSON 字符串時,將不會顯示 ID 。當然,你也可以像訪問屬性或者數組鍵那樣訪問獲得的屬性的 ID。
下一步則告訴 Laravel ,當 URL 包含模型的 UUID 時,則通過 uuid 列獲取模型。這將允許通過設置一個路由來查找模型,例如:
Route::get({podcast}, 'PodcastController@show');
然后在我們的 PodcastController 類中使用它。
/** * 通過 UUID 顯示播客 * * @param AppPodcast $podcast * @return IlluminateHttpResponse /* public function show(Podcast $podcast) { return response()->view('response', [ 'podcast' => $podcast ]); }
你也可以使用模型中的 resolveRouteBinding() 方法,你是否可以以編程的方式設置如何通過給定值來檢索模型。你甚至可以允許經過身份驗證的管理員根據記錄的 ID 或者 UUID 來獲取記錄。
就這樣,沒什么可做的了。該技術還允許在 應用程序生成后 設置 UUID 。
更多Laravel相關技術文章,請訪問Laravel教程欄目進行學習!