برای فقط‌خواندنی کردن یک اجرای کوئری، SQL را تجزیه (Parse) نکنید

از تلاش برای ایمن‌سازی پایگاه داده خود از طریق بررسی کلمات کلیدی در رشته‌های SQL دست بردارید.

اگر ابزاری برای اجرای SQL می‌سازید، به یک حالت فقط‌خواندنی (read-only) نیاز دارید. می‌خواهید از حذف ناخواسته داده‌ها توسط دستور UPDATE جلوگیری کنید. اولین فکر شما ممکن است مسدود کردن کلماتی مانند DELETE یا DROP باشد.

این کار را انجام ندهید.

دور زدن بررسی‌های رشته‌ای (String checks) آسان است. یک کاربر می‌تواند از عبارت WITH برای پنهان کردن یک DELETE استفاده کند. آن‌ها می‌توانند از کامنت‌ها برای مخفی کردن دستورات استفاده کنند. یا می‌توانند تابعی را فراخوانی کنند که در یک جدول می‌نویسد. در نهایت، شما درگیر بازی بی‌پایان و بازنده‌ای می‌شوید که در آن هر بار یک مشکل جدید ظاهر می‌شود.

اجازه دهید خودِ پایگاه داده امنیت را مدیریت کند.

Postgres یک قابلیت داخلی برای این کار دارد. شما می‌توانید یک تراکنش (transaction) را به عنوان read-only اعلام کنید. سپس سرور هرگونه دستور نوشتنی (write command) را رد می‌کند. این قابلیت شامل CTEها، توابع و DDL می‌شود.

روش اجرای صحیح آن در Python به این صورت است:

این رویکرد متن SQL را بازرسی نمی‌کند. کوئری دقیقاً همان‌طور که نوشته شده به سرور ارسال می‌شود. شما در واقع به موتور پایگاه داده می‌گویید که این قانون را اعمال کند.

امنیت به دو بخش نیاز دارد:

۱. محافظت در برابر عملیات نوشتنی: از تراکنش‌های read-only استفاده کنید. ۲. محافظت در برابر سوءاستفاده از منابع: از timeoutها و محدودیت تعداد ردیف‌ها استفاده کنید.

یک کوئری فقط‌خواندنی همچنان می‌تواند با یک join بسیار سنگین، سیستم شما را از کار بیندازد. یک تراکنش فقط‌خواندنی عملیات نوشتنی را متوقف می‌کند، اما مانع مصرف شدید منابع نمی‌شود. برای ایمن کردن SQLهای موردی (ad-hoc)، به هر دو نیاز دارید.

از تجزیه (parsing) SQL دست بردارید. از پایگاه داده بخواهید وظیفه‌اش را انجام دهد.

منبع: https://dev.to/hitoshi1964/dont-parse-sql-to-make-a-query-runner-read-only-b62