بعد أن شرحنا كيفية التحقق من صحة البيانات المدخلة من طرف العميل، ستفكر بعدها في كيفية إرسال هذه البيانات إلى الخادم، وهذا ما نغطيه في هذا المقال. إذ سنناقش ما يحدث عندما ينقر المستخدم على زر اﻹرسال في استمارات أو نماذج الويب Web Forms، وأين تذهب البيانات التي نرسلها وما الذي نفعله بها عندما تصل وجهتها، كما نلقي نظرة على بعض الاعتبارات اﻷمنية المتعلقة بإرسال بيانات استمارة الويب إلى الخادم.
ننصحك قبل المضي معنا في هذا المقال الاطلاع على أساسيات HTML وكذلك أساسيات بروتوكول HTTP وأن تلقي نظرة على أساسيات البرمجة في طرف الخادم.
ما سنفعله تاليًا هو شرح ما يحدث للبيانات عندما تُرسل بيانات نموذج من العميل client (وهو عادة متصفح الويب) إلى الخادم server.
معمارية عميل-خادم
يعمل الويب وفق معمارية تسمى عميل-خادم لتبادل البيانات ويمكن تلخيصها على النحو التالي: يُرسل العميل طلبًا إلى الخادم (خادم ويب في أغلب اﻷحيان مثل Apache أو Nginx أو IIS و Tomcat وغيرها) باستخدام بروتوكول HTTP، ثم يجيب الخادم على الطلب باستخدام نفس البروتوكول كما توضح الصورة التالية"
وهكذا ستكون الاستمارة في صفحة ويب طريقة ملائمة لتجميع البيانات التي يدخلها المستخدمون، وتهيئة طلب HTTP ﻹرسال تلك البيانات إلى الخادم.
ملاحظة: لتطلع أكثر على آلية عمل معمارية عميل-خادم، اطلع على مقال أساسيات البرمجة في طرف الخادم.
كيفية إرسال البيانات في طرف العميل
يُعرّف العنصر <form> كيفية إرسال البيانات، وقد صممت جميع خاصياته كي تسمح لك بإعداد طلب اﻹرسال عندما ينقر المستخدم على زر اﻹرسال submit. وتُعد action
و method
أهم خاصيتين لتهيئة عملية إرسال الطلب وإليك شرحًا لكل منهما.
الخاصية action
تُعرِّف هذه الخاصية وجهة البيانات التي نرسلها، وتكون قيمتها عنوان URL مطلق أو نسبي صالح. وإن لم تخصص قيمة لهذه الخاصية ستُرسل الاستمارة إلى عنوان URL لصفحة الويب التي تضمها. تُرسل البيانات في المثال التالي إلى عنوان مطلق Absolute URL وهو https://example.com
:
<form action="https://example.com">…</form>
بينا نستخدم في هذا المثال عنوان نسبي Relative URL ﻹرسال البيانات إلى عنوان URL آخر ضمن نفس النطاق، أي أنه يعتمد على موقع المورد الحالي.
<form action="/somewhere_else">…</form>
وفي حال لم نستخدم هذه الخاصية، ستُرسل بيانات الاستمارة إلى نفس الصفحة التي تضم الاستمارة أي لنفس عنوان URL الذي تم تحميل الاستمارة منه، ويمكن أن تُستخدم هذه الطريقة في بعض الحالات البسيطة مثل معالجة البيانات وعرض النتيجة على نفس الصفحة.
<form>…</form>
ملاحظة: من الممكن تخصيص عنوان URL يستخدم النسخة اﻵمنة من بروتوكول HTTP (بروتوكول HTTPS). وعندها تُشفَّر البيانات مع بقية أجزاء الطلب حتى لو كانت الاستمارة ضمن صفحة غير آمنة تستخدم بروتوكول HTTP. لكن، ومن ناحية أخرى، إن كانت الاستمارة ضمن صفحة آمنة وكان عنوان URL الذي خصصته للخاصية action
غير آمن (يستخدم HTTP) سيعرض المتصفح رسالة تحذير في كل مرة يحول فيها المستخدم إرسال الاستمارة لأن البيانات لن تكون مشفَّرة.
تُرسَل بيانات الاستمارة إن لم تكن ملفًا على شكل أزواج مكونة من اسم و قيمة name=value
تربط بينها علامة &
، ويجب أن تكون قيمة الخاصية action
ملفًا على الخوادم التي تستطيع التعامل مع هذا النوع من الملفات وتتأكد من صلاحيتها. يستجيب الخادم بعد ذلك، وعادة ما يعالج البيانات ويحمّل عنوان URL الذي تحدده الخاصية action
مسببًا إعادة تحميل الصفحة (أو تحديث الصفحة إن كانت موجودة، إن أشارت الخاصية action
إلى نفس الصفحة). لكن كيف ترسل البيانات؟ يعتمد اﻷمر هنا على قيمة الخاصية method
.
الخاصية method
تعرف هذه الخاصية كيفية إرسال البيانات. إذ يوفر بروتوكول HTTP عدة طرق لتنفيذ الطلبات، ويمكن للاستمارة أن تستخدمها في إرسال بياناتها إلى الوجهة المحددة، وأكثر هذه الطلبات شيوعًا GET
و POST
.
ولفهم الاختلاف بين الطلبين السابقين، علينا معرفة آلية عمل بروتوكول HTTP. ففي كل مرة تحاول الحصول فيها على مورد من الويب، يرسل المتصفح طلبًا إلى عنوان URL. ويتكون هذا الطلب من قسمين:
- ترويسة الطلب header تضم مجموعة من البيانات الوصفية العامة حول إمكانيات المتصفح.
- جسم الطلب body الذي يضم البيانات الضرورية التي يحتاجها الخادم لمعالجة الطلب.
الطلب GET
يستخدم المتصفح هذا الطلب كي يطلب من الخادم موردًا محددًا: " مرحبا! أريد هذا المورد". فيُرسل المتصفح في هذه الحالة جسم طلب فارغ، وطالما أن الجسم فارغ ستُرسل بيانات الاستمارة إلى الخادم ملحقةً بعنوان URL. لنتأمل الحالة التالية:
<form action="http://www.foo.com" method="GET"> <div> <label for="say">What greeting do you want to say?</label> <input name="say" id="say" value="Hi" /> </div> <div> <label for="to">Who do you want to say it to?</label> <input name="to" id="to" value="Mom" /> </div> <div> <button>Send my greetings</button> </div> </form>
طالما أننا استخدمنا الطلب GET
، سيكون عنوان URL كالتالي:
www.foo.com/?say=Hi&to=Mom
وسيظهر في شريط عنوان المتصفح بهذا الشكل عند النقر على زر اﻹرسال:
لاحظ كيف ألحقت البيانات بعنوان URL على شكل أزواج اسم=قيمة تأتي بعد إشارة ?
ويفصل بين كل زوج المحرف &
. وقد مرنا في حالتنا البيانات التالية إلى الخادم:
-
الاسم
say
قيمتهHi
. -
الاسم
to
قيمتهMom
.
سيدو عنوان URL عندها بالشكل:
GET /?say=Hi&to=Mom HTTP/2.0 Host: foo.com
ملاحظة: لن تُلحق البيانات إن لم يكن عنوان URL المخصص قادرًا على التعامل مع الاستعلامات (أن يكون ملفًا مثلًا).
الطلب POST
يختلف هذا الطلب قليلًا عن GET
، ويستخدمه المتصفح ليطلب من الخادم استجابة تتعلق بالبيانات التي يرسلها ضمن جسم طلب HTTP: " مرحبًا! ألق نظرة على هذه البيانات وأعد نتيجة مناسبة". تلحق الاستمارة البيانات بجسم طلب HTTP عند استخدام POST
، ولكي نميز الفرق، ألق نظرة على نفس استمارة المثال السابق لكن باستخدام الطلب POST
:
<form action="http://www.foo.com" method="POST"> <div> <label for="say">What greeting do you want to say?</label> <input name="say" id="say" value="Hi" /> </div> <div> <label for="to">Who do you want to say it to?</label> <input name="to" id="to" value="Mom" /> </div> <div> <button>Send my greetings</button> </div> </form>
لا تُلحق بيانات الاستمارة بعنوان URL في حال استخدمت الطلب POST
بل ستكون ضمن جسم الطلب الذي سيبدو بالشكل:
POST / HTTP/2.0 Host: foo.com Content-Type: application/x-www-form-urlencoded Content-Length: 13 say=Hi&to=Mom
تشير الترويسة Content-Length
إلى حجم جسم الطلب، والترويسة Content-Type
إلى نوع المصدر الذي ترسله إلى الخادم، وسنناقش هاتين الترويستين لاحقًا.
ملاحظة:سيُستخدم الطلب GET
إن لم يكن عنوان URL المخصص قادرًا على التعامل مع جسم الطلب (كأن يكون على الشكل :data
مثلًا).
عرض طلبات HTTP
لا تُعرض طلبات HTTP للمستخدم أبدًا، ولكن إن أردت رؤيتها ومعرفة تفاصيل الطلبات واستجابة الخادم عليك استخدام بعض اﻷدوات مثل أدوات مطوري ويب على كروم أو مراقب الشبكة على فايرفوكس. وكمثال على ذلك، بإمكانك استعراض بيانات المثال السابق ضمن نافذة شبكة كروم Chrome Network بعد إرسال الاستمارة كالتالي:
-
افتح نافذة أدوات مطوري ويب developer tools.
-
اختر "شبكة Network".
-
اختر "الكل All".
-
اختر الموقع الذي تريد وليكن "foo.com" في النافذة "اسم Name".
-
اختر "ترويسات Headers".
يمكنك عندها الحصول على بيانات النموذج Form Data كما في لقطة الشاشة التالية:
ما عُرض على المستخدم هنا هو عنوان URL الذي استدعاه فقط. وكما قلنا سابقًا، سيرى المستخدم البيانات ملحقة بعنوان URL ضمن شريط عنوان المتصفح عندما يستخدم الطلب GET
، لكنه لن يرى شيئًا إن كان الطلب هو POST
، ولهذا اﻷمر أهميته لسببين:
-
لا تستخدم
GET
على اﻹطلاق إن أردت إرسال كلمة مرور (أو غيرها من البيانات الحساسة)، لأن هذه البيانات ستُعرض ضمن العنوان وهذا غير آمن. -
يُفضّل استخدام
POST
إن احتجت إلى إرسال كمية كبيرة من البيانات. إذ تحدد بعض المتصفحات حجم عناوين URL، كما تحدد الخوادم أيضًا طول عناوين URL التي تقبلها.
كيف تستخلص البيانات في طرف الخادم
أيًا كان طلب HTTP الذي استخدمته، ستصل البيانات إلى الخادم على شكل نصي يُفسره لاستخلاص البيانات على شكل قائمة من الأزواج مفتاح/قيمة. أما طريقة التعامل مع هذه القائمة، فتعود إلى بيئة التطوير أو إطارات العمل التي تستخدمها.
مثال على إرسال البيانات للخادم باستخدام لغة PHP صرفة
تقدم PHP بعض الكائنات العامة للوصول إلى البيانات في طرف الخادم. فلو افترضنا أنك استخدمت الطلب POST
كما في المثال التالي، سيعرض هذا المثال البيانات المرسلة للمستخدم فقط. وبالطبع، يعود اﻷمر إليك فيما تفعله بهذه البيانات، فقد تعرضها أو تخزنها في قاعدة بيانات أو ترسلها ضمن بريد إلكتروني وهكذا..
<?php // الوصول إلى البيانات المستلمة باسمها $_POST يتيح لك المتغير العام //$_GET نستخدم المتغير GET وللوصول إلى البيانات المرسلة باستخدام الطلب $say = htmlspecialchars($_POST['say']); $to = htmlspecialchars($_POST['to']); echo $say, ' ', $to; ?>
يعرض هذا المثال صفحة ويب تضم البيانات التي أرسلناها، يضم ملف المثال نفس استمارة التمرين السابق وتكون قيمة الخاصية method
هي POST
وقيمة الخاصية action
هي php-example.php
. عند النقر على زر اﻹرسال، يُرسل المتصفح البيانات إلى الملف php-example.php
الذي يضم الشيفرة التي عرضناها سابقًا، وستكون نتيجة تنفيذ هذه الشيفرة كالتالي:
ملاحظة: لن يعمل المثال السابق إن حملته ضمن المتصفح مباشرة، فلا يمكن للمتصفحات تفسير لغة PHP. لهذا عندما ترسل الاستمارة، سيعرض المتصفح تحميل ملف PHP فقط. كي يعمل هذا الملف، لابد من تنفيذه على خادم يدعم PHP. ومن الخيارات المتاحة لاختبار PHP محليًا نقترح MAMP ( على نظام التشغيل ويندوز وماك أو إس) و AMPPS (على نظام ويندوز وماك و لينكس).
وفي حال استخدمت MAMP ولم تكن قد ثبّته مسبقًا (أو كانت نسخة تجريبية انتهت صلاحيتها) فقد تواجهك بعض المشكلات عند تشغيل الملف. ولكي يعمل مجددًا، حمل التطبيق واختر NAMP>Preferences>PHP
ثم اضبط قيمة Standard Version
على*.7.2
وستختلف قيمة *
وفقًا للنسخة التي ثبّتها.
مثال على إرسال البيانات للخادم باستخدام لغة بايثون
سنعرض في هذه الفقرة نفس المثال السابق لكن باستخدام لغة بايثون وإطار العمل فلاسك Flask لتصيير القوالب والتعامل مع بيانات الاستمارة. بإمكانك الاطلاع على ملف المثال على جيت-هاب:
from flask import Flask, render_template, request app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def form(): return render_template('form.html') @app.route('/hello', methods=['GET', 'POST']) def hello(): return render_template('greeting.html', say=request.form['say'], to=request.form['to']) if __name__ == "__main__": app.run()
يتعامل المثال السابق مع قالبين ينبغي أن يكونا ضمن مجلد فرعي باسمtemplates
في نفس المجلد الذي يضم الملف python-example.py
إن أردت تشغيل المثال بنفسك:
-
القالب
form.html
: وهو ملف يضم نفس الاستمارة التي تعاملنا معها في المثال السابق، لكن ضبطت قيمة الخاصيةaction
لتكون{{('helo')url_for}}
. يُدعى هذا القالب قالب Jinja وهو أساسًا ملف HTML لكن يمكن أن يضم استدعاءات لشيفرة بايثون التي تعمل على الخادم بوضعها ضمن أقواس معقوصة. وتعني الشيفرةurl_for('hello')
: انتقل إلى الوجهةhello/
عند إرسال الاستمارة. -
القالب
greeting.html
: ويضم فقط شيفرة لتصيير البيانات التي نمررها إليه عندما تكون جاهزة. وينفذ اﻷمر باستخدام الدالة()hello
التي تُنفذ عند الانتقال إلى الوجهةhello/
.
ملاحظة: لن يعمل المثال السابق إن حملته ضمن المتصفح مباشرة، إذ تعمل لغة بايثون بشكل مختلف قليلًا عن PHP. لتنفيذ هذا المثال على متصفحك عليك تثبيت وإعداد Python ، ثم تثبيت Flask باستخدام اﻷمر pip3 install flask
. وبعد الانتهاء من المفترض أن تتمكن من تشغيل المثال باستخدام python3 python-example.py
. بعد ذلك اكتب العنوان التالي في متصفحك localhost:5042
.
لغات وإطارات عمل أخرى
ستجد العديد من التقنيات المتوفرة للتعامل مع الاستمارات في طرف الخادم بما في ذلك بيرل Perl وجافا Java وروبي Ruby ودوت نت Net وغيرها. ومن الجدير بالذكر أن استخدام هذه التقنيات مباشرة ليس شائعًا لأن التعامل معها قد يكون مربكًا. لهذا من اﻷفضل العمل مع إطارات عمل عالية الجودة تُسهّل التعامل مع الاستمارات مثل:
-
إطارات عمل بايثون:
-
جانغو Django
-
فلاسك Flask
-
web2py (سهلة للمبتدئين).
-
py4web (طوّرت من قبل نفس مطوري wep2py لكنها تشبه دجانغو قليلًا من ناحية اﻹعداد).
-
-
إطارت عمل Node.js
-
إطارات PHP
-
لارافيل Laravel
-
سمفوني Symfony
-
-
إطارات Ruby
-
إطارات جافا
-
Spring Boot
-
وتجدر اﻹشارة إلى أن العمل مع الاستمارات لن يكون سهلًا بالضرورة عند استخدام أطر العمل، لكنه أسهل بكثير مقارنة مع كتابة جميع الوظائف الضرورية من الصفر، وتوفر عليك الوقت والجهد بالتأكيد.
لن تتعلم بالطبع من أمثلة هذا المقال كل ما تحتاجه للعمل مع لغات البرمجة من طرف الخادم فهو غير مخصص لهذا اﻷمر، لكنك ستجد الكثير من المقالات المفيدة التي تساعدك على الانطلاق ضمن أكاديمية حسوب وموسوعة حسوب، إضافة إلى دورات البرمجة التي تبدأ بك من الصفر حتى الاحتراف وإعداد معرض اﻷعمال.
حالة خاصة: إرسال ملف
تُمثَّل البيانات في الملف على شكل بيانات ثنائية -أو تُعد كذلك- بينما تكون بقية أنواع البيانات المرسلة نصية. وطالما أن HTTP هو بروتوكول نصي، هناك متطلبات خاصة للتعامل مع البيانات الثنائية.
الخاصية enctype
تسمح لك هذه الخاصية بتحدبد قيمة الترويسة Content_Type
في طلب HTTP الذي ينتج عن تسليم الاستمارة. وهذه الترويسة مهمة جدًا لأنها تخبر الخادم عن نوع البيانات التي أرسلت. تأخذ الخاصية افتراضيًا القيمة التالية application/x-www-form-urlencoded
والتي
تعني: "هذه بيانات استمارة شُفرت ضمن عنوان URL". لكن إن أردت إرسال ملف، عليك تنفيذ الخطوات اﻹضافية التالية:
-
اضبط قيمة الخاصية
method
علىPOST
لأن محتوى الملف لا يمكن وضعه ضمن عنوان URL. -
اضبط قيمة الخاصية
enctype
علىmultipart/form-data
لأن البيانات ستُجزّأ إلى أقسام متعددة : قسم لكل ملف وقسم للبيانات النصية التي يضمها جسم الطلب (في حال وجدت بيانات نصية أخرى في الاستمارة). -
استخدام عنصر
<'input type='file>
أو أكثر لتسمح للمستخدم باختيار الملف أو الملفات التي يريد رفعها.
إليك مثالًا:
<form method="post" action="https://www.foo.com" enctype="multipart/form-data"> <div> <label for="file">Choose a file</label> <input type="file" id="file" name="myFile" /> </div> <div> <button>Send the file</button> </div> </form>
ملاحظة: قد تُهيّأ الخوادم لتقبل حجمًا محدودًا للملفات أو طلبات HTTP لمنع الاستخدام غير الصحيح لمواردها.
اعتبارات أمنية
عليك الانتباه إلى أية اعتبارات أمنية قبل إرسال البيانات إلى الخادم، لأن استمارات HTML حتى اللحظة هي أكثر النقاط التي تهاجم الخوادم منها. وليست المشكلة في الاستمارة نفسها، بل بكيفية تعامل الخادم مع بيانات الاستمارة.
ننصحك بالاطلاع على مقال "تعرف على أمان مواقع الويب" الذي يناقش أكثر الهجمات شيوعًا والطرق الممكنة لصدها، لكي تكوّن تصورًا واضحًا عما يمكن أن يحدث.
كن مرتابًا ولا تثق أبدًا بالمستخدم
إن القاعدة الأهم والتي عليك تذكرها دائمًا هي: لا تثق أبدًا بالمستخدمين بمن فيهم أنت، فقد يتعرض أي مستخدم حتى الموثوقون إلى هجمات سرقة البيانات. لهذا يجب أن تتحقق دائمًا من كل البيانات التي تصل إلى الخادم وتنقيها دون أي استثناء.
- تجاوز escape أي محرف قد يشكل خطرًا: تختلف المحارف التي يجب الانتباه إليها حسب سياق البيانات المدخلة ومنصة عمل الخادم. وتمتلك جميع لغات البرمجة التي تعمل من طرف الخادم دوال للتعامل مع هذه اﻷمور. أما اﻷشياء التي عليك مراقبتها فهي أي تسلسل لمحارف تبدو وكأنها شيفرة تنفيذية (مثل جافا سكريبت أو أوامر SQL).
- حدد كميات البيانات التي يمكن استقبالها: حتى تسمح بإرسال البيانات الضرورية فقط.
- احتجز الملفات المرفوعة إلى الخادم: خزّن هذه الملفات على خادم مختلف واسمح بالوصول إليها عبر نطاقات فرعية أو اﻷفضل عبر نطاقات مختلفة تمامًا عن نطاق موقعك.
ستتجنب الكثير من المشاكل المتعلقة باﻷمان وحتى معظمها إن اتبعت الخطوات السابقة. مع ذلك، من اﻷفضل أن تنفذ اختبارًا امنيًا بمساعدة طرف خارجي، فلا تفترض أبدًا أنك حددت جميع المشاكل المحتملة.
الخلاصة
إن إرسال البيانات للخادم أمر سهل نسبيًا، لكن تأمين التطبيق من خطر هذه البيانات أمر مربك، وتذكر دائمًا أن مطور واجهة المستخدم ليس الشخص المسؤول عن وضع نموذج لتقييم سلامة البيانات. وعلى الرغم من إمكانية إجراء تقييم لصلاحية البيانات في طرف العميل، لكن لا يمكن للخادم الوثوق بهذا التقييم، لأنه لا يعرف إطلاقًا ما يحدث حقيقية في طرف العميل.
وهكذا نكون قد وصلنا إلى نهاية هذه السلسلة التي تحدثنا فيها عن استمارات الويب وطرق إنشائها وتنسيقها والتحقق من صلاحية بياناتها ثم إرسال البيانات إلى الخادم.
ترجمة -وبتصرف- للمقال: Sending form data
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.