امنیت درخواست در وردپرس

افزایش امنیت درخواست GET در برنامه نویسی استارتاپ وردپرس

یکی از بزرگترین اشتباهاتی که توسعه دهندگان وردپرس در برنامه نویسی قالب و افزونه انجام می دهند ، استفاده مستقیم از متغیر های GET در برنامه نویسی php می باشد.این امر ن تنها مسیر داده را لو می دهد بلکه در مواردی منجربه حملات شدید SQL Injection و در نتیجه هک شدن وب سایت می گردد.به کد های زیر برای درخواست GET در وردپرس دقت کنید :

فرض کنید برگه ای ایجاد کردیم با slug یا نامک user و در آن می خواهیم به ازای دریافت شناسه کاربر (User id) ، اطلاعات کاربری آن را نمایش دهیم.عموم افراد این درخواست را به این صورت برنامه نویسی می کنند :

if (is_page('user')) {
$user_id = trim($_GET['user_id']);
if( isset($user_id) and $user_id !="" and is_numeric($user_id) ) {
$user_info = get_userdata($user_id);
if($user_info ===false) {
	echo 'کاربری با این شناسه یافت نشد';
} else {
	echo $user_info->last_name .  ", " . $user_info->first_name . "\n";
}
} else {
echo 'درخواست نامعتبر می باشد';
}
}

و آدرس صفحات سایت هم بدین صورت جایگذاری می کردیم :

http://example.com/user/?user_id=5

در مثال بالا ابتدا چک کرده این که آیا یک GET با نام user_id در صفحه درخواست ارسال شده است یا خیر سپس در مرحله بعدی اطلاعات کاربر با شناسه 5 درخواست و اگر جواب مثبت بود نام و نام خانوادگی کاربر در سایت به نمایش در می آمد.

اما این روش کاملا اشتباه است …

دریافت اطلاعات کوئری اصلی یا Main Query در وردپرس

همان طور که می دانید در هر صفحه یک کوئری اصلی (Main Query) با توجه به محتویات و شناسه صفحه در پایگاه داده وردپرس درخواست شده و به کاربر نمایش داده می شود.به همین دلیل هست زمانی که ما تنها در صفحه ای تابه the_content را می نویسیم بطور خودکار وردپرس محتویات آن صفحه که در ویرایشگر آن وارد کرده ایم را برایمان به نمایش در می آورد.حال این محتویات از طریق کدام کوئری به دیتابیس ارسال شد خوب معلوم است توسط کوئری اصلی یا Main Query.

برای نمایش جزئیات کامل آرایه کوئری اصلی کافیست از متغیر wp_query$ بصورت جهانی یا global در صفحه استفاده کنید.

//Get Global Varible
global $wp_query;

//Show Variable
echo '<pre>';
print_r($wp_query);

اگر این کد را مثلا در صفحه single.php قالب خود قرار دهید یک آرایه کامل از جزئیات آن صفحه مشاهده خواهید کرد.مثلا اگر میخواهید عنوان یک نوشته را در صفحه single.php دریافت کنیم تنها کافیست بنویسیم :

global $wp_query;
echo $wp_query->queried_object->post_title;

اگر با دقت کنید خواهید دید که در عضو اول آرایه wp_query یک آرایه با نام query وجود دارد.این دقیقا همان جایی است که ما به آن نیاز داریم.
برای افزایش امنیت درخواست های GET در وردپرس می بایست متغیر های هر صفحه را به Query آن صفحه الحاق کنیم.

آموزش ایجاد End Point در درخواست های وردپرس

برای افزایش امنیت درخواست در مثال بالا چه بهتر است آدرس درخواست را به این شکل در بیاوریم :

http://example.com/user/profile/xx

در آدرس بالا بجای xx شناسه کاربر در وردپرس قرار میگیرد.این یک آدرس کاملا استاندارد و ایمن هست.
برای این که یک متغیر در پایان آدرس صفحات یا همان End Point بتوانیم تعریف کنیم ، از تابع add_rewrite_endpoint در مستندات وردپرس استفاده می کنیم.این تابع شامل دو پارامتر بسیار مهم است :

add_rewrite_endpoint( $name, $places );

بخش اول می بایست نام آرگومان یا پارامتری که میخواهیم به پایان آدرس اضافه شود را قرار دهیم در مثال بالا عبارت profile را باید قرار دهیم زیرا به وردپرس می فهمانیم ما یک آرگومان ورودی با نام profile نیاز داریم.
در بخش دوم این تابع شما باید مشخص کنید که در چه مدل صفحاتی در وردپرس این پارامتر قابل اجرا هست.همانطور که که میدانید در وردپرس مدل صفحات متفاوتی داریم مثلا صفحه دسته ها ، صفحه برگه ها ، صفحه ی نوشته ها ، صفحه ی آرشیو ها و ..
پس ما در این پارامتر برای ایجاد امنیت درخواست مشخص میکنیم که فقط در فلان نوع صفحه این پارامتر قابل ورود به کوئری اصلی یا Main Query دارد.وردپرس برای این پارامتر مقدار های مشخصی را تعیین کرده که در زیر برایتان لیست کرده ام :

  1. EP_PERMALINK  (در صفحه نوشته ها)
  2. EP_ATTACHMENT  (در صفحه رسانه ها)
  3. EP_DATE  (در صفحه آرشیو)
  4. EP_YEAR (در صفحه آرشیو سالانه)
  5. EP_MONTH  (در صفحه آرشیو ماهانه)
  6. EP_DAY  (در صفحه آرشیو روزانه)
  7. EP_ROOT  (در صفحه اصلی سایت)
  8. EP_COMMENTS  (در درخواست نظرات)
  9. EP_SEARCH  (در صفحه جستجوی سایت)
  10. EP_CATEGORIES  (در صفحه دسته ها)
  11. EP_TAGS  (در صفحه برچسب ها)
  12. EP_AUTHORS  (در صفحه نویسندگان)
  13. EP_PAGES  (در صفحه برگه ها)
  14. EP_ALL  (در تمامی صفحات ، که برای افزایش امنیت پیشنهاد میکنم استفاده نکنید مگر آن که واقعا لازم باشد)

اگر هم میخواهید دو شرط را با هم اجرا کنید میتوانید از | برای جداسازی آن ها استفاده کنید.مثلا من میخواهم یک مقدار ورودی با نام view را برای صفحات برچسب و دسته ها فعال کنم پس باید بنویسم :

add_rewrite_endpoint( 'view', EP_CATEGORIES | EP_TAGS  );

خوب برگردیم به مثال خودمان ، میخواستیم یک ورودی به نام profile را برای یک برگه که با نامک user در وردپرس ایجاد کردیم فعال کنیم.

add_action('init', function() {
	add_rewrite_endpoint('profile', EP_PAGES);
});

دو نکته را همیشه در زمان کار با آدرس ها در وردپرس دقت کنید :

  1. اول اینکه برای ایجاد یک route یا مسیر جدید و یا حتی اضافه کردن یک متغیر مانند مثال بالا بهتر هست تابع در زمان init Action فراخوانی شود یعنی ابتدای کارو
  2. هر زمان که تغییراتی در endpoint یا route در وردپرس انجام دادیم ، حتما میبایست تنظیمات آن بازگردانی یا Flush Rewrite شوند. برای این کار اگر با cli وردپرس آشنایی ندارید کافیست در بخش مدیریت سایت وردپرس ، بخش تنظیمات ، پیوند های یکتا شوید و یک بار گزینه ذخیره تنظیمات را بزنید.

تغییر پیوند یکتا وردپرس

حالا اگر آدرس example.com/user/profile/5 را در وردپرس خود درخواست کنیم و کد زیر را بنویسیم یک مقدار جدید به آرایه کوئری اصلی (Main Query) ما اضافه خواهد شد :

get_query_arg در وردپرس

خوب دیگر کار تمام است میتوانیم براحتی این مقدار را از wp_query دریافت کرده و در برنامه نویسی خودمان بررسی کنیم.

global $wp_query;
if( ! $wp_query->query_vars['profile'] ) {
echo 'درخواست نا معتبر هست';
}

آموزش تابع get_query_var در وردپرس

اگر میخواهید از نوشتن عبارت wp_query خلاص شوید ، این کار توسط تابع get_query_var در وردپرس انجام می شود.
این تابع دقیقا آرایه query_vars را برایمان برمیگرداند و هر عضوی را که میخواهید ، میتوانید دریافت کنید.همچنین یک پارامتر دوم هم دارد که به شما امکان قرار دادن یک مقدار دلخواه زمانی که این ورودی وجود نداشت را میدهد به مثال زیر دقت کنید :

$profile = get_query_var("profile", 0);
echo $profile;

در مثال بالا ابتدا query_var با نام profile را از صفحه درخواست کردیم ، درصورتی که این مقدار وجود نداشت متغیر profile مقدار صفر بارگزاری می شود.

جمع بندی امنیت درخواست در وردپرس

اگر کدهای بالا را بخواهیم در یک مثال اذغام کنیم بدین صورت در می آید.این کد ها را من در فایل functions.php قالب خود اضافه میکنم و سپس پیوند های یک تا را یکبار flush می کنم.

add_action('init', 'wps_add_endpoints');
function wps_add_endpoints() {
	add_rewrite_endpoint('profile', EP_PAGES);
}
add_filter( 'the_content', 'my_the_content_filter', 20 );
function my_the_content_filter( $content ) {
	if (is_page('user')) {
		$user_id = get_query_var("profile");
		if( isset($user_id) and $user_id !="" and is_numeric($user_id) ) {
			$user_info = get_userdata($user_id);
			if($user_info ===false) {
				echo 'کاربری با این شناسه یافت نشد';
			} else {
				echo $user_info->last_name .  ", " . $user_info->first_name . "\n";
			}
		} else {
			echo 'درخواست نامعتبر می باشد';
		}
	}
	// Returns the content.
	return $content;
}



مطلب رو به اشتراک بگذارید