URL에 데이터베이스 ID를 노출하지 마십시오.

웹 앱을 개발할 때 우리는 종종 데이터베이스에서 정보를 가져오는 데 의존합니다. 프레임워크는 ORMs 덕분에 이를 쉽게 할 수 있는 방법을 제공합니다.

대부분의 경우 ORM은 기본 키를 신뢰할 수 있는 식별자로 사용하여 모델을 찾습니다. 대부분의 기본 키는 자동으로 증가하는 정수입니다.

그러면 URL이 다음과 같이 표시됩니다.

https://example.com/cart/12
https://example.com/user/15/post/41
...

부정확하거나 결함이 있는 권한 부여 계층을 제공하면 데이터 유출이 발생할 수 있습니다. 사용자는 데이터에서 데이터로 이동할 수 있게 됩니다. 이는 사용자 개인 정보와 같은 민감한 데이터에 관한 것이라면 허용하고 싶지 않은 것입니다.

식별자 난독화



이 보안 침해를 완화하는 쉬운 방법은 다음과 같은 키를 사용하는 것입니다.
  • 예측하기 어려운
  • 아이템 간의 통일성을 유지하면서 많은 아이템을 생성할 수 있을 만큼 충분히 무작위
  • 코드 및 데이터베이스에서 쉽게 생성
  • 확인 가능(유효 여부는 무결성을 분석하여 알 수 있음)

  • 덕분에 UUIDs이 매우 적합한 후보입니다. 위의 모든 사항을 확인하고 사용할 준비가 된 다양한 패키지 덕분에 사용하기가 매우 쉽습니다.

    이제 URL을 예측하기 어려워져 앱의 인증 정책과 관련된 개발자의 실수를 완화합니다.

    https://example.com/cart/f6e4208f-5df4-466e-9225-01f296e2a09c
    https://example.com/user/b1b44b12-34bc-4ed7-a666-9657b8b8c31b/post/e530d034-42f7-467b-91e3-1cc9313312eb
    

    Laravel 앱의 예



    Laravel 패키지 개발을 연습하고 처음으로 Github Workflow 을 사용하기 위해 이 작업을 쉽게 할 수 있도록 패키지를 만들었습니다.

    지금 앱에서 khalyomede/laravel-eloquent-uuid-slug을 사용하는 방법은 다음과 같습니다.

    패키지 설치



    먼저 콘솔로 이동하여 다음 명령을 입력합니다.

    composer require khalyomede/laravel-eloquent-uuid-slug
    

    마이그레이션에 슬러그 열 추가



    그런 다음 원하는 migrationmodel으로 이동하거나 이미 설치된 경우 새로 만들고 슬러그 열을 추가하십시오.

    namespace Database\Migrations;
    
    use App\Models\Cart;
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    
    final class AddSlugColumnToCartTable extends Migration {
      public function up(): void
      {
        Schema::table('carts', function (Blueprint $table): void {
          Cart::addSlugColumn($table);
        });
      }
    
      public function down(): void
      {
        Schema::table('carts', function (Blueprint $table): void {
          Cart::dropSlugColumn($table); // available soon in v0.2.0
        });
      }
    };
    

    모델에 특성 추가



    이것은 Route model binding 을 사용하여 경로에서 모델을 검색하는 방법을 구성하는 데 도움이 되는 마지막 단계입니다.

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    use Khalyomede\EloquentUuidSlug\Sluggable;
    
    final class Cart extends Model
    {
      use Sluggable;
    }
    

    컨트롤러에서 사용



    이제 패키지를 사용할 준비가 되었습니다. 그것의 좋은 점은 코드가 변경되지 않는다는 것입니다! 익숙한 방식으로 route() 방법을 계속 사용할 수 있습니다.

    // routes/web.php
    
    use App\Models\Cart;
    use Illuminate\Http\RedirectResponse
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Route;
    use Illuminate\View\View;
    
    Route::get("cart/{cart}", function (Cart $cart): View {
      return view("cart.show", [
        "cart" => $cart,
        "saveCartRoute" => route("cart.store", $cart),
      ]);
    })->name("cart.show");
    
    Route::post("cart/{cart}", function (Request $request, Cart $cart): RedirectResponse {
      $cart->update($request->only(["name"]));
    
      return redirect()->route("cart.show", $cart);
    })->name("cart.store");
    

    그리고 짜잔! 이 패키지는 보시다시피 기존 논리를 방해하지 않습니다. 변경되는 유일한 것은 이제 경로가 노출되지 않는다는 것입니다.

    route("cart.show", $cart); // https://example.com/cart/398e76a7-7c16-467c-93a8-04c06c6df703
    

    결론



    이 솔루션은 데이터 유출의 초기 문제를 해결하는 마법 같은 방법은 아니지만 악의적인 사용자가 시스템을 속일 가능성을 줄이는 매우 쉬운 실행 가능한 메커니즘이라는 것을 알았습니다.

    이것은 예를 들어 Laravel Policies과 같은 인증 또는 보호 메커니즘을 추가하는 것을 막지 않습니다. 예를 들어 사용자가 자신이 만들지 않은 장바구니로 이동하는 경우 볼 수 없어야 합니다.

    여기 다른 사람들이 이미 이 주제에 대해 이야기했으므로 UUID 사용에 대해 더 자세히 알고 싶다면 꼭 읽어보세요.














    행복한 URL 강화!

    좋은 웹페이지 즐겨찾기