تابع real_escape_string() در PHP
در برنامهنویسی وب، یکی از مهمترین مسائل امنیتی جلوگیری از حملات SQL Injection است. تابع real_escape_string() در PHP ابزاری برای پاکسازی رشتهها (escaping) قبل از قرار دادن در یک عبارت SQL است تا کاراکترهای ویژه که میتوانند ساختار کوئری را تغییر دهند، ایمن شود. معمولاً این تابع به شکل متدی از کلاس mysqli یا تابع mysqli_real_escape_string() استفاده میشود.
هدف اصلی و محدوده کاربرد
- جلوگیری از خرابسازی رشتههای SQL با قرار دادن بکاسلش قبل از کاراکترهای خطرناک (مثلاً نقل قولها).
- مناسب برای مواقعی که از کوئریهای دینامیک استفاده میکنید و به هر دلیل نمیتوانید از کوئریهای پارامتری (prepared statements) بهره ببرید.
- نکته: این تابع جایگزین کامل prepared statement نیست؛ بهترین روش همیشه استفاده از پارامترایز کردن کوئری است.
نحو و استفاده پایهای
// اتصال با mysqli
$mysqli = new mysqli("localhost", "user", "pass", "db");
// مقدار ورودی کاربر
$user_input = $_POST['username'];
// فرار دادن رشته قبل از استفاده در کوئری
$safe = $mysqli->real_escape_string($user_input);
$sql = "SELECT * FROM users WHERE username = '$safe'";
$result = $mysqli->query($sql);
در این مثال، متد real_escape_string روی رشته ورودی اجرا میشود تا از نقل قولها و بکاسلشهای مخرب محافظت کند. سپس رشتهٔ امن در داخل کوئری به صورت ایمنتر قرار میگیرد.
توضیح فنی و نکات مهم
- برای اینکه فراردهی صحیح انجام شود، باید اتصال به دیتابیس (موجودیت mysqli) باز و به درستی تنظیم شده باشد؛ چرا که فراردهی بسته به charset کانکشن انجام میشود.
- اگر کاراکترنگاشت (character set) اتصال با کاراکترنگاشت دیتابیس همسان نباشد، احتمال بروز مشکل یا عبور رشتهٔ مخرب وجود دارد.
- این تابع فقط کاراکترها را escape میکند؛ ساختار منطقی کوئری همچنان در اختیار شماست و اگر کوئری بهصورت پویا ساخته شود، خطرات دیگری ممکن است وجود داشته باشد.
مثال روی ورودی شامل تککوتیشن
$name = "O'Reilly";
$safe = $mysqli->real_escape_string($name);
// $safe becomes: O'Reilly
$sql = "INSERT INTO authors (name) VALUES ('$safe')";
$mysqli->query($sql);
در این مثال، نقلقول تکی موجود در نام با بکاسلش محافظت میشود و بنابراین کوئری از شکستن جلوگیری میکند.
محدودیتها و مواردی که باید بدانید
- real_escape_string تنها برای رشتههاست؛ اگر مقادیر عددی دارید، بهتر است آنها را به طور صریح cast کنید (مثلاً
(int)$id). - برای دادههای باینری یا فایلها نیز باید از متدهای مناسب مانند prepared statements با نوع BLOB استفاده کنید.
- اگر بهطور کامل امنیت میخواهید، از prepared statements و binding پارامترها استفاده کنید؛ این روش فارغ از charset و انواع داده، امنتر است.
مقایسهٔ سریع: real_escape_string vs prepared statements
| ویژگی | real_escape_string | Prepared Statements |
|---|---|---|
| سهولت پیادهسازی | متوسط — نیاز به فراردهی دستی | معمولی — نیاز به تعریف پارامترها |
| مقاومت در برابر SQL Injection | خوب در شرایط صحیح | بسیار خوب — ایمنترین روش |
| پشتیبانی از انواع داده | محدود (رشته) | تمام انواع (INT, BLOB, …) |
| وابستگی به charset | بله | کمتر وابسته |
نمونهٔ بهتر: استفاده از Prepared Statements (توصیه شده)
// Prepared statement با mysqli
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$result = $stmt->get_result();
در این حالت نیازی به فراردهی دستی نیست. پارامترها به صورت ایمن به کوئری متصل میشوند و ریسک SQL Injection به حداقل میرسد.
موارد عملی و مثالهای استفاده
- وقتی از یک کتابخانه یا سیستم قدیمی استفاده میکنید که امکان بازنویسی به prepared statements وجود ندارد، از
real_escape_string()استفاده کنید اما با رعایت نکات charset. - برای پرسوجوهای پیچیده که شامل بخشهای ثابت و متغیر است، میتوانید متغیرها را قبل از الحاق به رشتهٔ کوئری با این تابع فراردهی کنید.
- همیشه ورودیهای کاربر را نیز اعتبارسنجی (validation) کنید؛ escaping تنها بخشی از دفاع است.
اشتباهات رایج
- فراردهی رشته بدون تنظیم charset کانکشن: اگر
charsetتنظیم نشود، برخی کاراکترها ممکن است بهدرستی فرار نشوند. - فراموش کردن فراردهی قبل از تازهنویسی یا درج در کوئری.
- اعتماد کامل به
real_escape_stringبه جای استفاده از prepared statements.
نتیجهگیری و بهترین راهکارها
تابع real_escape_string() ابزار مفیدی برای کاهش ریسک SQL Injection است، اما باید با دقت و دانش استفاده شود: اتصال فعال، charset هماهنگ و شناخت محدودیتهایش ضروری است. بهترین و مدرنترین روش حفاظت استفاده از prepared statements و پارامترایز کردن کوئریها است. در صورتی که به هر دلیل مجبور به استفاده از escaping هستید، مطمئن شوید که تمامی ورودیها پاکسازی و اعتبارسنجی میشوند و charset کانکشن به درستی تنظیم شده است.
آیا این مطلب برای شما مفید بود ؟



