احراز هویت توکن در php با JWT


شاید علاقه مند باشید که احراز هویت (Authentication) در وب چگونه انجام می شود ؟ در مقاله قبلی به معرفی احراز هویت توکن در php با سیشن و jwt پرداختیم . در این آموزش , قصد داریم بصورت کاملتر و البته عملی احراز هویت JWT در php را نشان دهیم .

در مقابل نشست ها (Sessions)

قبلا تنها راه برای برطرف کردن مشکل stateless بودن HTTP و احراز هویت خودتان در یک بخش مدیریت برنامه تحت وب وارد کردن اطلاعات ورود بود .

بعدها سرویس API ها وارد شدند و ارسال اطلاعات ورود بصورت متن ساده (plain text) قابل قبول نبود.  امروزه ایده توکن API ها مطرح است و بسیاری از این روش استفاده می کنند .

 

یکی از معایب وارد کردن اطلاعات ورود و برقرار کردن وضعیت (state) کاربر برای ارتباط با اپلیکیشن توسط کوکی های سئشن موارد زیر بود :

  • داده ها بصورت متن ساده در سرور ذخیره می شد

هرچند که داده ها در فولدر عمومی ذخیره نمی شود , هرکسی دسترسی خواندن فایل های سئشن را داشت (امنیت سیشن در php)

  • درخواست های خواندن/نوشتن (read/write) فایل سیستم

هر بار که سیشن استارت میشد یا داده های آن تغییر پیدا می کرد . سرور نیاز داشت که فایل سیشن را بروزرسانی کند. این عملیات با هر بار ارسال سیشن کوکی ها تکرار می شد.

که در نهایت اگر تعداد کاربران زیادی داشتید , باعث کاهش سرعت سرور می شود.

 

زمانی که با سرویس های API سروکار دارید , نیاز است که برای هر درخواستی که ارسال می کنید , کلید (key) خود را هم همراه ان ارسال کنید (در هدر درخواست مانند Authorization , api-key و یا در url بصورت querystring) .

JWT

از اکتبر ۲۰۱۰ ,سرویس های زیادی از توکن های مبتنی بر JSON استفاده می کنند . JWT یا JSON Web Token دارای مشخصات زیر است :

  1. مورد استفاده در محیط هایی با فضای کاراکتری محدود مثل هدرهای احراز هویت HTTP یا پارامتر های querystring است.
  2. داده ها باید به فرمت JSON یا همان Javascript Object Notation انتقال پیدا کنند.
  3. داده باید دارای تکه کدی از امضای json باشد.
  4. بصورت اینکودینگ Base64  برگشت داده می شود.

JSON Web Signature یک مکانزیم رمزنگاری است که برای امن کردن داده با یک امضای دیجیتال است که برای توکن استفاده می شود تا از اینکه آیا داده دستکاری شده و یا توسط فرد دیگری دزدیده و دوباره استفاده شده یا نه .

 

مزایای استفاده از JWT ها به جای یک Api Key

Api Key ها فقط یک رشته تصادفی هستند در حالی که JWT ها شامل اطلاعات و متا-داده (metadata)هایی که میتواند idکاربر , اطلاعات احراز هویت ذخیره و  اعتبار سنجی توکن بر اساس زمان یا دامنه را انجام دهد.

  • JWT ها نیاز به یک منبع متمرکز برای صدور/لغو مجوز ندارند.
  • با OAUTH2 سازگار است.
  • داده های JWT قابل بررسی دوباره است .
  • توانایی کنترل بر تاریخ انقضای JWT ها وجود دارد.

 

رشته JWT به چه صورت است ؟

یک JWT رشته ای مشابه زیر است :

شاید بنظر برسد که یک رشته با کاراکتر های تصادفی است که به هم متصل شدند. و با API key ها تفاوتی ندارند. به هر حال اگر به دقت نگاه کنید , ۳ رشته متفاوت با نقطه (.) از هم جدا شده اند .

رشته اول و دوم رشته های JSON بصورت Base64 اینکد شده اند و اگر آنها را دیکد کنید نتیجه زیر را خواهید دید:

  1. رشته اول هدر JWS است که نشان می دهد که الگریتم رمزنگاری شده برای ساخت payload است و همچنین نوع پیلود را مشخص میکند .
  2. رشته دوم خود payload است که همراه چند فیلد استاندارد , هر داده ای که قصد داشتید را با توکن ارسال می کنید .
  3. رشته سوم یک امضای رمزنگاری شده است و بصورت داده باینری دیکد می شود .

چیزی که در مورد امضای JWT است , نوع الگریتم رمزنگاری هستش که نیاز به یک secret key دارد , رشته ای که فقط خود اپلیکیشن آن را می داند و به هیچ طریقی نباید لو رود .

به اینصورت وقتی اپلیکیشن ,توکن را دریافت می کند ,  JWT Signature یا همان امضا را بر طبق توکن را با secret key می تواند اعتبارسنجی کند . اگر تایید موفقیت آمیز نبود , می توانید اطمینان پیدا کنید که داده داخل توکن دستکاری شده است و باید درخواست پس زده شود .

می توانید با مراجعه به jwt.io با انواع encoding,decofing های JWT آشنا شوید .

انجام عملی احراز هویت توکن در php با JWT

خب فرض کنیم یک مکانیزم لاگین با استفاده از سئشن و کوکی ها را داریم . البته توجه کنید JWT جایگزین سئشن و کوکی ها نیست . به هر حال برای این مثال چند سرویس خواهیم داشت : یکی برای ساخت یوزنیم و پسورد و دیگری هم برای ارایه یک ریسورس محافظت شده ای که با JWT معتبر قابل دسترس است.

احراز هویت توکن در php با JWT

همینکه لاگین شدیم , میتوانیم به منابع محافظ شده از اپلیکیشن دسترسی داشته باشیم .

برای شروع احراز هویت توکن در php با JWT , php-jwt را با کامپوزر composer require firebase/php-jwt (composer چیست) نصب می کنیم . همچنین اپلیکیشن نمونه برای این آموزش توسعه داده شده است . همچنین از zend-config , zend-http بهره می بریم که اگر دوست داشتید میتوانید آن ها را بصورت زیر نصب کنید:

یک کتابخانه php دیگر نیز برای JWT وجود دارد (jose) که می توانید از آن استفاده کنید.

حالا فرض کنیم که فرم لاگین اطلاعات را به سرویس JWT ما از طریق AJAX ارسال می کند , زمانی که اطلاعات ورود با اطلاعات ذخیره شده دیتابیس بررسی و تایید شد , ما توکن را می سازیم .

ابتدا آن را بصورت یک آرایه می سازیم :

برای کپی صحیح و کامل کدها ، دابل کلیک کرده تا وارد محیط سفید و کپی شوید در غیر اینصورت امکان دارد اجرای کدها با مشکل روبرو شود

لطفا توجه کنید که ساختار داده را به هر صورت که خواستید می توانید تعریف کنید , چند مقدار از پیش تعریف شده وجود دارد که تعدادی از آن را در کد php بالا به کار بردیم :

  • Jat –  مقدار timestamp ساخت توکن
  • Jti – یک رشته یکتا که میتواند برای اعتبارسنجی توکن استفاده شود
  • Iss – یک رشته که شامل نام یا ID اپلیکیشن است که میتواند نام دامنه هم باشد.
  • Nbf – مقدار timestamp زمانی که توکن معتبر است . که باید مساوی یا بزرگتر از آن باشد .
  • Iat – در اینجا , توکن برای ۱۰ ثانیه معتیر است.
  • Exp – مقدار timestamp زمانی که توکن معتبر است که باید بزرگتر از iat و nbf باشد . در این مورد , توکن بعد از ۶۰ ثانیه معتبر است

استفاده تمام موارد بالا اجباری نیست اما به شما در ادامه به اعتبارسنجی توکن کمک خواهد کرد . payload اپلیکیشن ما زمانی که مقدار userId,username ذخیره میشود در data قرار می گیرد . توجه داشته باشید هنگامی که JWT به هیچ عنوان اطلاعات حساس مثل پسورد ها را در JWT وارد نکنید.

تبدیل این آرایه به یک JWT بسیار ساده است :

JWT::encode() تمام کار ها را انجام می دهد (تبدیل آرایه به داده JSON , تولید هدرها ,ساخت payload و اینکد رشته نهایی). می توانید secret key را طولانی , باینری و اینکد کنید و در فایل config ذخیره کنید . اما ذخیره مستقیم آن در کد ها ایده بدی است !

حالا کلاینت توکن را دارد , می توانید آن را توسط JS یا هر مکانیزمی که دوست دارید ذخیره کنید . یک مثال از آن را با jQuery میبینیم :

 

حالا یک ریسورس که توسط مکانیزم JWT محافظت شده است را بازیابی میکنیم .

احراز هویت توکن در php با JWT

زمانی که بر روی دکمه “Get resource >>” کلیک می کنید , اگر همه چی اوکی باشد , باید یک تصویر را در محیط خاکستری رنگ ببینید .حالا از ajax برای ارسال درخواست به منبع سرویس استفاده می کنیم .

توجه داشته باشید از گزینه beforeSend استفاده کردیم . ما به jQuery می فهمانیم که قبل از ارسال هر درخواستی این تابع را اجرا کن که نیاز داریم با این کار هدر Authorization را با مقدار JWT در فرمت Bearer [JWT] اجرا کنیم .  پس زمانی که بر روی دکمه کلیک میکنیم درخواست زیر ارسال می شود :

حتما بخوانید  معرفی احراز هویت Token در php

حالا می توانیم منبع محافظت شده را ببینیم .

احراز هویت توکن در php با JWT

نحوه اعتبارسنجی توکن در سرویس منبع بصورت زیر است :

من از Zend\Http\PhpEnvironment\Request برای ساده تر کردن کارها هنگام استخراج نوع و هدر درخواست HTTP بهره می برم .

حالا بیایید ببینیم آیا یک رشته JWT در هدر Authorization وجود دارد یا خیر.

یکی از راه های جایگزین که ممکن است به جای استفاده از هدرهای Authorization در درخواست HTTP , پاس دادن آن به عنوان پارامتر URL است :

حالا قصد داریم که JWT را دیکد کنیم . توجه داشته باشید که ما قبلا از Secret Key برای ساختن توکن استفاده کردیم که در این مرحله هم از آن بهره می بریم.

اگر هنگام دیکد کردن JWT به مشکل برخوردیم ممکن است :

  1. طول رشته داده شده با استاندارد ۳ بخشی که قبلا توضیح دادیم یکسان نیست
  2. هدر یا payload یک رشته معتبر JSON نیست .
  3. امضای رمزنگاری صحیح نیست که به این معنا است که داده دستکاری شده است !!
  4. مقدار nbf یا iat که در jwt با timestamp تعریف شده است ازtimestamp فعلی کمتر است .
  5. مقدار exp که همراه JWT ست شده است کمتر از timestamp فعلی کمتر است .

همانطور می بینید , JWT یک کنترل خوب بر روی مقادیر غیرمعتبر دارد بدون آنکه نیاز به ساخت مجدد آن داشته باشد و یا آن را بر اساس لیست توکن های معتبر دارد .

 

در نهایت یک تصویر را از lorempixel.com را درخواست می کنیم , آن را بصورت base64 اینکد و بصورت رشته json در پاسخ ارسال می کنیم .

اگر قصد داشته باشید , می توانید سورس نمونه احراز هویت توکن در php با JWT را  باکس دانلود دریافت و مطابق راهنما پیش برید و دقیق تر کد ها را بررسی کنید .

احراز هویت توکن در php با JWT

جمع بندی

از این به بعد می توانید تلاش کنید که JWT را در REST API های خود استفاده کنید , شاید هم سعی کنید از الگوریتم های دیگری مثل RS256 برای ساخت امضا استفاده کنید و یا حتی این مورد را با احراز هویت OAUTH2 از قبل ساخته شده بر روی سرور ادغام بدید .

امیدوارم از آموزش پیاده سازی احراز هویت توکن در php با JWT لذت برده باشید و در ساخت REST API های خود استفاده کنید.

هر سوالی در مورد احراز هویت Token در php داشتید ، از قسمت نظرات ارسال کنید . سریعا ، پاسخگوی سوالات شما هستیم .

موفق و پیروز باشید

حسن شفیعی
مدرس ، پنتستر ، توسعه دهنده اپلیکیشن های تحت وب ، عضو مرکز حامی نخبگان و از مدیران و اعضای رسمی تیم امنیتی آشیانه هستم . علاقه خاصی به زبان php و امنیت شبکه و لینوکس دارم و هر روز تلاش می کنم به این حوزه ها مسلط تر شوم و اطلاعاتم را در وب به اشتراک بگذارم

دیدگاه کاربران

2 پاسخ به “احراز هویت توکن در php با JWT”

  1. قاسم صابری گفت:

    سلام متشکر از مطلب مفیدتون برای استفاده از jwt در فریمورک کدایگنایتر باید به عنوان کتابخانه اضافه کنیم آیا ؟ راهکار استفاده رو اگر برام بفرستین یا لینک مفید قرار دهید ممنون میشم

    0

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

جدیدترین آموزش های آنلاین



دانلود رایگان (هدیه ویژه)

کتاب آموزش زبان برنامه نویسی PHP را دانلود و همین امروز یادگیری را شروع کن و به جمع برنامه نویسان ملحق شو ;)

دانلود رایگان کتاب

نظر کاربران عزیز

آموزش های آنلاین در چه زمینه ای تهیه کنیم ؟

نظر شما برای ما بسیار مهم است

Loading ... Loading ...

بخش کاربران

هنوز عضو نیستید ؟ کلیک کنید

دانلود کتاب

عضویت در خبرنامه