آموزش جاوا اسکریپت – جلسه ۲۴ – کوکی [cookie]

سلام دوستان و همراهان عزیز راهکارینو، در مقاله قبل (بخش 23 از آموزش جامع جاوا اسکریپت) نحوه تغییر عناصر DOM را آموزش دادیم. تولید یک عنصر جدید (createElement)، درج عنصر، حذف عنصر و کپی کردن عناصر موجود. در این مقاله قصد دارم با یک مبحث کاربردی و کلاسیک در زبان جاوا اسکریپت در خدمتتون باشم. کوکی (Cookie).
کوکی (Cookie) چیست؟
مرورگرهای وب و سرورها از پروتکل http برای برقراری ارتباط با یکدیگر استفاده می کنند. در وب سایت های تجاری لازم است که برخی از داده ها بین صفحات مختلف سایت ذخیره شوند. کوکی ها داده هایی از نوع رشته هستند که مستقیما در مرورگر ذخیره می شوند.
کوکی ها معمولا توسط وب سرورها تنظیم می شوند. با تعریف Set-Cookie در بخش HTTP-header پاسخ سرور (response). سپس مرورگر این کوکی را از سرور دریافت کرده و روی تمام درخواست ها (request) به دامین آن وب سایت کوکی را اضافه می کند.
یکی از رایج ترین کاربردهای کوکی احراز هویت (Authentication) می باشد.
مراحل احراز هویت کاربر در سایت توسط cookie:
- پس از لاگین کاربر، سرور کوکی مربوط به آن را توسط Set-Cookie در HTTP-header پاسخش (response) ذخیره می کند.
- دفعه بعدی که یک درخواست به همان دامین داده شود، مرورگر کوکی ذخیره شده را به سمت سرور ارسال می کند.
- در اینصورت سرور میفهمد که چه کسی درخواست را ایجاد کرده است.
نکته: می توانیم با استفاده از دستور document.cookie در جاوا اسکریپت، کوکی مرورگر را بخوانیم.
نکات زیادی درباره کار با cookie در جاوا اسکریپت وجود دارد که ما در ادامه این مقاله سعی داریم آنها را بررسی کنیم.
خواندن کوکی از document.cookie:
برای اینکه متوجه شوید که آیا در یک سایت مشخص کوکی ذخیره می شود یا خیر کافیست دستور زیر را در کنسول مرورگر اجرا کنید. می توانید با زدن کلید F12 کنسول را باز کنید:
alert( document.cookie ); // cookie1=value1; cookie2=value2;...
مقدار داخل document.cookie شامل جفت های name=value می باشد که بوسیله سمی کالن (;) از یکدیگر جدا شده اند. هر کدام از آنها یک کوکی مجزا می باشند.
بعنوان مثال با اجرای دستور فوق در کنسول سایت tgju پیغام زیر را خواهیم داشت:
نوشتن کوکی در document.cookie:
ما همچنین می توانیم علاوه بر خواندن کوکی از document.cookie، کوکی را در آن بنویسیم. عملیات write فقط کوکی ذکر شده را آپدیت می کند و کاری با بقیه کوکی هایی که از قبل ست شده اند ندارد.
بعنوان مثال کد زیر یک کوکی با کلید user و مقدار John ست می کند:
document.cookie = "user=John"; // update only cookie named 'user' alert(document.cookie); // show all cookies
اگر کدهای بالا را در کنسول مرورگر اجرا کنید، تمام کوکی ها را در پیغام alert مرورگر خواهید دید. اگر کلید user از قبل در کوکی وجود داشته باشد، مقدار آن را آپدیت می کند. اگر وجود نداشته باشد آن را بعنوان آخرین مقدار در کوکی ذخیره می کند.
بعنوان مثال در همان مثال tgju می خواهیم کد فوق را اجرا کنیم. خواهیم داشت:
مشاهده می شود که کوکی جدید با کلید user و مقدار John بعنوان آخرین کوکی تعریف شده است.
دقت کنید که تعداد کوکی هایی که در هر دامین میتواند تعریف شود حدود 20 تاست. تعداد دقیق آن به نوع مرورگر بستگی دارد.
آپشن های کوکی در جاوااسکریپت:
کوکی ها تنظیمات زیادی دارند. برخی از آنها مهم هستند و باید حتما تعریف شوند.
Samesite, secure, expires, max-age, domain, path
در کد زیر برخی از آپشن های کوکی تعریف شده اند:
document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"
تعریف Path در کوکی:
نحوه تعریف: path=/mypath
با تعریف path می گوییم کوکی در تمام صفحات زیر مجموعه path قابل دسترسی باشد. بصورت پیش فرض برابر با مسیر (path) جاری است.
بعنوان مثال اگر path برابر path=/admin تعریف شود، بیانگر اینست که کوکی مربوطه در صفحه admin و تمام صفحات زیرمجموعه آن قابل دسترسی است. مانند /admin/something اما در مسیری مثل /home این کوکی تعریف خواهد بود.
در حالت عادی ما باید path را بصورت path=/ تعریف کنیم تا کوکی در تمام صفحات سایت قابل دستیابی باشد.
تعریف domain در کوکی:
نحوه تعریف: domain=site.com
نام دامنه ای که cookie در آن قابل دسترسی است. محدودیت هایی دارد و ما نمی توانیم هر دامنه ای را تعریف کنیم. بطور پیش فرض آپشن دامین برابر دامنه ای است که کوکی در آن ست شده است. بنابراین اگر کوکی در دامنه site.com ست شده است نمی تواند در دامنه other.com به آن دسترسی داشت.
نکته دیگر اینست که اگرکوکی در دامین site.com تعریف شده باشد نمی تواند در ساب دامین آن مثلا forum.site.com به آن کوکی دسترسی داشت. مثال زیر:
// at site.com document.cookie = "user=John" // at forum.site.com alert(document.cookie); // no user
نکته: هیچ راهی وجود ندارد که بتوان از کوکی ست شده در دامین site.com در دامین دیگر مانند other.com استفاده کرد.
آپشن domain در کوکی به این دلیل است که بتوانیم از کوکی دامین site.com در زیر دامنه های آن مثلا forum.site.com استفاده کرد. کد زیر را مشاهده کنید:
// at site.com // make the cookie accessible on any subdomain *.site.com: document.cookie = "user=John; domain=site.com" // later // at forum.site.com alert(document.cookie); // has cookie user=John
در کد بالا، کوکی user=John را در دامین site.com ست کرده ایم و domain را برابر site.com تعریف کرده ایم. در اینصورت کوکی user در ساب دامین forum.site.com قابل دسترسی خواهد بود.
نکته: اگر می خواهید کد بالا در مرورگرهای قدیمی کار کند، باید بصورت domain=.site.com تعریف شود.
تعریف expires, max-age:
تعریف Expires در کوکی:
بطور پیش فرض اگر آپشن های expires و max-age را برای کوکی تعریف نکنیم، در صورت بسته شدن پنجره مرورگر، کوکی نیز از بین می رود. به این نوع کوکی ها session cookie گفته می شود.
برای اینکه به کوکی اجازه دهیم پس از بسته شدن تب مرورگر هم زنده بماند، می توان یکی از آپشن های expires یا max-age را تعریف کرد. بصورت زیر:
expires=Tue, 19 Jan 2038 03:14:07 GMT
با تعریف کد بالا، مرورگر بطور اتوماتیک کوکی را در تاریخ 19 ژانویه سال 2038 از مرورگر کاربر پاک می کند. تاریخ/زمان باید دقیقا با فرمت فوق تعریف شود. یعنی GMT Timezone.
می توانیم با استفاده از متد date.toUTCString تاریخ انقضای کوکی را تعیین کرد. بعنوان مثال در کد زیر گفتیم که کوکی یک روز تاریخ مصرف دارد:
// +1 day from now let date = new Date(Date.now() + 86400e3); date = date.toUTCString(); document.cookie = "user=John; expires=" + date;
نکته: اگر تاریخ انقضای کوکی را برابر تاریخ گذشته (مثلا یکهفته پیش) تعریف کنیم، کوکی حذف می شود.
تعریف max-age در کوکی:
روش جایگزین تعریف تاریخ انقضای کوکی، استفاده از max-age است که واحد آن ثانیه می باشد. اگراین زمان برابر صفر یا عدد منفی تعریف شود، کوکی حذف می شود. بعنوان مثال در کد زیر ابتدا تاریخ اتمام کوکی را یکساعت اعلام کردیم. سپس پشیمان شدیم و با صفر کردن max-age آن را منقضی کردیم!
// cookie will die +1 hour from now document.cookie = "user=John; max-age=3600"; // delete cookie (let it expire right now) document.cookie = "user=John; max-age=0";
تعریف secure در cookie:
Cookie فقط باید از طریق پروتکل https یا http منتقل شود. بطورپیش فرض، کوکی تعریف شده در دامین https://site.com در دامین http://site.com نیز قابل دستیابی است و برعکس.
این بدین معنی است که کوکی بطور پیش فرض بر اساس نام دامین کار می کند و برایش فرقی ندارد پروتکل مورد استفاده سایت http است یا https.
بنابراین توصیه می شود اگر کوکی شامل داده های حساس است، نباید آن را بر روی پروتکل نا امن http منتقل کرد و باید آن را محدود به https کرد. بصورت زیر:
// assuming we're on https:// now // set the cookie secure (only accessible if over HTTPS) document.cookie = "user=John; secure";
تعریف httpOnly در کوکی:
گاهی اوقات ممکن است وب سرور کوکی موردنظر خود را با آپشن httpOnly ارسال کند. در این حالت، دیگر نمی توان توسط جاوا اسکریپت و با متد document.cookie کوکی را خواند یا در آن چیزی نوشت.
در واقع httpOnly دسترسی جاوا اسکریپت را به cookie مسدود می کند.
این آپشن بدلایل امنیتی تعریف شده است. زیرا ممکن است هکر با تزریق اسکریپت های مخرب جاوااسکریپتی در صفحه وب، منتظر ورود کاربر به صفحه باشد و اطلاعات او را سرقت کند. مثلا هکر می تواند با استفاده از اسکریپت مخرب، داده های مربوط به لاگین کاربران در سایت را به سرقت ببرد.
اگر آپشن httpOnly برای کوکی تعریف شده باشد، هکر دیگر قادر به اجرای دستورات جاوا اسکریپتی بر روی کوکی سایت نخواهد بود و کوکی محفوظ می ماند.
توابع کار با کوکی (Cookie Functions):
جاوا اسکریپت برای کار با کوکیها (cookies) یک سری توابع کاربردی دارد که ساده تر از تغییر کوکی توسط document.cookie هستند.
تابع getCookie(name):
سریع ترین روش برای دسترسی به کوکی استفاده از عبارت باقاعده (regular expression) می باشد. تابع getCookie کوکی مرتبط با نام name را برمیگرداند.
بدنه تابع getCookie به شکل زیر تعریف شده است:
// returns the cookie with the given name, // or undefined if not found function getCookie(name) { let matches = document.cookie.match(new RegExp( "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" )); return matches ? decodeURIComponent(matches[1]) : undefined; }
نکته: در کد بالا، عبارت new RegExp بصورت داینامیک تولید می شود. دقت کنید که مقدار کوکی (cookie value) به شکل کد شده (encoded) ذخیره می شود. در اسکریپت فوق توسط تابع decodeURIComponent مقدار کوکی را رمزگشایی (decode) کرده ایم.
بعنوان مثال اگر بخواهیم مقدار کوکی user را دریافت کنیم تابع getCookie(‘user’) را اجرا می کنیم.
تابع setCookie(name, value, options):
تابع setCookie یک کوکی را با نام و مقدار ارسال شده و آپشن path=/ بصورت پیش فرض تعریف می کند.
کد پیاده سازی شده تابع setCookie:
function setCookie(name, value, options = {}) { options = { path: '/', // add other defaults here if necessary ...options }; if (options.expires instanceof Date) { options.expires = options.expires.toUTCString(); } let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value); for (let optionKey in options) { updatedCookie += "; " + optionKey; let optionValue = options[optionKey]; if (optionValue !== true) { updatedCookie += "=" + optionValue; } } document.cookie = updatedCookie; }
و نحوه استفاده از تابع setCookie برای تعریف یک کوکی جدید:
// Example of use: setCookie('user', 'John', {secure: true, 'max-age': 3600});
در کد بالا یک cookie با نام user و مقدار John ست کرده ایم که آپشن secure برابر true (یعنی تنها از طریق پروتکل https قابل دسترسی است) و آپشن max-age برابر 3600 ثانیه (یعنی زمان انقضای آن یکساعت است).
تابع deleteCookie(name):
برای پاک کردن کوکی، می توان یک مقدار منفی برای تاریخ انقضا (expiration-date) تعریف کرد:
function deleteCookie(name) { setCookie(name, "", { 'max-age': -1 }) }
نکته: آپدیت یا دیلیت کردن کوکی باید دارای آپشن های path و domain یکسان باشند.
مثال های کوکی در جاوا اسکریپت:
مثال اول: می خواهیم یک کوکی با نام ورودی کاربر در تکست باکس تعریف کنیم:
<html> <head> <script type = "text/javascript"> <!-- function WriteCookie() { if( document.myform.customer.value == "" ) { alert("Enter some value!"); return; } cookievalue = escape(document.myform.customer.value) + ";"; document.cookie = "name=" + cookievalue; document.write ("Setting Cookies : " + "name=" + cookievalue ); } //--> </script> </head> <body> <form name = "myform" action = ""> Enter name: <input type = "text" name = "customer"/> <input type = "button" value = "Set Cookie" onclick = "WriteCookie();"/> </form> </body> </html>
مثال دوم: می خواهیم لیست تمام کوکی های ست شده در یک وب سایت را دریافت کنیم:
<html> <head> <script type = "text/javascript"> <!-- function ReadCookie() { var allcookies = document.cookie; document.write ("All Cookies : " + allcookies ); // Get all the cookies pairs in an array cookiearray = allcookies.split(';'); // Now take key value pair out of this array for(var i=0; i<cookiearray.length; i++) { name = cookiearray[i].split('=')[0]; value = cookiearray[i].split('=')[1]; document.write ("Key is : " + name + " and Value is : " + value); } } //--> </script> </head> <body> <form name = "myform" action = ""> <p> click the following button and see the result:</p> <input type = "button" value = "Get Cookie" onclick = "ReadCookie()"/> </form> </body> </html>
جمع بندی:
Document.cookie دسترسی به کوکی را فراهم می کند:
- عملیات نوشتن در کوکی، فقط روی کوکی ذکر شده اعمال می شود.
- مقادیر name/value باید کدگذاری شوند.
- هر کوکی می تواند حداکثر 4 کیلوبایت باشد و ماکزیمم می توان حدود 20 کوکی در یک سایت ذخیره کرد. البته بستگی به نوع مرورگر هم دارد.
تنظیمات کوکی:
- Path=/ بطور پیش فرض برابر مسیر جاری است. کوکی در این مسیر و مسیرهای زیرمجموعه آن قابل دسترسی خواهد بود.
- Domain=site.com بطور پیش فرض domain برابر نام دامین جاری می باشد ولی اگر می خواهید کوکی در ساب دامین های یک سایت معتبر باشد باید آپشن domain=site.com را تعریف کنید.
- Expires یا max-age باعث می شوند کوکی در زمان دلخواه ما منقضی (یا حذف) شود. در صورتی که آپشن تاریخ انقضای کوکی تعریف نشود، با بستن تب مرورگر، کوکی هم از بین خواهد رفت.
- Secure باعث می شود کوکی فقط از طریق پروتکل HTTPS منتقل شود.
- SameSite از ارسال کوکی به درخواست های خارج از سایت جلوگیری می کند.
⇐ مطالعه مقاله “تفاوت cookie با web storage” پیشنهاد می شود.
در اینجا، آموزش کار با کوکی ها در جاوا اسکریپت به پایان می رسد. در مقاله بعد (بخش 25 آموزش javascript)، سوالات رایج جاوا اسکریپت که در مصاحبه های استخدامی شرکت ها مطرح می شوند را به همراه پاسخ تشریحی بررسی خواهیم کرد.
کاربران گرامی لطفا سوالات و پیشنهادهای خود را درباره این مقاله در قسمت دیدگاه ها ارسال کنید.
دیدگاهتان را بنویسید