در این مقاله، اصول این که JWTها (نشانههای وب JSON = JSON Web Tokens) چه هستند و برای چه استفاده میشوند را توضیح خواهیم داد. JWTها یک بخش بسیار مهم برای تضمین اعتماد و امنیت در برنامهها است. JWTها باعث میشوند که مواردی مانند دادههای کاربر به روشی امن نمایش داده شوند.
برای توضیح نحوه کار JWT، بیایید با یک تعریف چکیده شروع کنیم:
یک JWT، در واقع یک آبجکت JSON است که در RFC 7519 به عنوان روشی برای نمایش مجموعهای از اطلاعات به صورت امن میان دو شخص تعریف شده است. این token از یک header، یک payload و یک نشانه تشکیل شده است.
به صورت ساده، یک JWT رشتهای است که دارای این قالب میباشد:
header.payload.signature
نکته: یک رشته که در یک «“”» قرار دارد، یک آبجکت JSON معتبر به حساب میآید.
برای نمایش این که JWTها چرا و چگونه بنا شدهاند، از سه مثال موجودیت استفاده میکنیم. موجودیتهای این مثال شامل کاربر، سرور برنامه و سرور احراز هویت هستند. سرور احراز هویت، JWT را برای کاربر فراهم میکند و کاربر با داشتن JWT، میتواند به صورت امن با برنامه در ارتباط باشد.
در این مثال، کاربر ابتدا با استفاده از سیستم ورود سرور احراز هویت به آن وارد میشود. سپس سرور احراز هویت JWT را ایجاد میکند و آن را به کاربر میفرستد. وقتی که کاربر یک فراخوانی API به برنامه ارسال میکند، در واقع JWT را نیز به همراه آن فراخوانی ارسال میکند. در این روند، سرور برنامه به گونهای پیکربندی شده است که صحت ساخته شدن JWT ورودی توسط سرور احراز هویت را تایید کند. پس وقتی که کاربر فراخوانیهای API را به همراه JWT ارسال میکند، برنامه میتواند از JWT استفاده کرده، و تایید کند که فراخوانیهای API از کاربر احراز هویت شده میآیند.
حال، خود JWT و نحوه ساخت و تایید آن با عمق بیشتری توضیح داده خواهد شد.
قدم ۱ - HEADER را بسازید
کامپوننت Header در JWT، شامل اطلاعاتی درباره نحوه محاسبه نشانه JWT است. Header یک آبجکت JSON در این قالب است:
{
"typ": "JWT",
"alg": "HS256"
}
در این JSON، مقدار کلید typ مشخص میکند که آبجکت یک JWT است، و مقدار کلید alg تعیین میکند که کدام الگوریتم hashing برای ساخت کامپوننت نشانه JWT استفاده میشود. ما در این مثال، از الگوریتم HMAC-SHA256 استفاده میکنیم؛ یک الگوریتم hashing که از یک کلید مخفی برای محاسبه نشانه استفاده میکند.
قدم 2- PAYLOAD را بسازید
کامپوننت Payload در JWT دادهای است که داخل JWT ذخیره شده است. در مثال ما، سرور احرار هویت یک JWT به همراه اطلاعات کاربر، مخصوصا ID او در داخل آن میسازد.
{
"userId": "b08f86af-35da-48f2-8fab-cef3904660bd"
}
ما در مثال خود فقط یک مورد را داخل Payload قرار میدهیم، گرچه به یاد داشته باشید که میتوانید هر تعدادی که میخواهید را در آن قرار دهید. دقت کنید که حجم دادهها، حجم کلی JWT را تحت تاثیر قرار میدهند. معمولا این باعث بروز مشکل نمیشود، اما داشتن حجم بسیار بالای JWT میتواند کارایی را تحت تاثیر قرار دهد و باعث بروز تاخیر شود.
قدم 3- نشانه (SIGNATURE) را بسازید
نشانه از طریق این شبه کد محاسبه میشود:
// signature algorithm
data = base64urlEncode( header ) + “.” + base64urlEncode( payload )
hashedData = hash( data, secret )
signature = base64urlEncode( hashedData )
کاری که این الگوریتم میکند، این است که header و payload که در قدمهای ۱ و ۲ ساخته شدند را به روش base64url انکود میکند. سپس این الگوریتم رشتههای انکود شده را با یک «.» در میان آنها ادغام میکند. در شبه کد ما، این رشته ادغام شده به data اختصاص داده شده است. این data با استفاده از الگوریتم مشخص شده در header، و با کلید مخفی hash شده است. نتیجه به دست آمده به hashedData اختصاص داده شده است. سپس این داده hash شده به صورت base64url انکود میشود تا نشانه JWT را تولید کند.
در مثال ما، هم header و هم payload به این صورت به روش base64url انکود شدهاند:
// header
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
// payload
eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ
سپس، با اعمال الگوریتم نشانه مشخص شده به همراه کلید مخفی، ما دادههای hash شده مورد نیاز برای نشانه را به دست میآوریم؛ که در این مورد یعنی اعمال الگوریتم HS356 بر روی دادهها، برای به دست آوردن hashedData. در نهایت ما این نشانه JWT را به دست میآوریم:
// signature
-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM
قدم 4- هر ۳ کامپوننت JWT را سر هم کنید
حال که هر سه کامپوننت را ساختهایم، میتوانیم خود JWT را بسازیم. با به یاد داشتن ساختار header.payload.signature در JWT، به راحتی میتوانیم این سه کامپوننت را با یک نقطه در میان آنها ترکیب کنیم. ما از نسخه انکود شده به صورت base64url از header، payload و نشانه که در قدم سوم به آنها پرداختیم استفاده میکنیم.
// JWT Token
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ.-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM
حال سرور احراز هویت ما میتواند این JWT را به کاربر ارسال کند.
JWT چگونه از دادههای ما مراقبت میکند
درک این که چگونه هدف JWTها مخفی کردن یا مبهمسازی دادهها نیست، بسیار مهم است. علت استفاده از JWTها این است که ثابت کنیم دادههای ارسال شده در حقیقت توسط یک منبع معتبر ساخته شدهاند. همانطور که در قدمهای قبلی توضیح داده شد، JWSها انکود و نشانهگذاری میشوند، نه رمزنگاری. هدف از انکود، تغییر شکل دادن ساختار دادهها است. نشانهگذاری دادهها شما را قادر میسازد تا اعتبار منبع داده را تایید کنید. پس انکود کردن و نشانهگذاری کردن دادهها را امن نمیکنند.
قدم 5 - تایید JWT
ما در سه مثال موجودیت خود، از یک JWT که توسط الگوریتم HS256 نشانهگذاری شده است استفاده میکنیم، که فقط سرور احراز هویت و سرور برنامه کلید مخفی را میدانند. وقتی که برنامه روند احراز هویت را شروع میکند، سرور برنامه کلید مخفی را از سرور احراز هویت دریافت میکنند. وقتی که کاربر یک فراخوانی API متصل شده به JWT را به برنامه ارسال میکند، از آنجایی که برنامه آن کلید مخفی را میداند، میتواند الگوریتم نشانهگذاری در قدم ۳ را بر روی JWT پیاده کند. سپس برنامه میتواند نشانه دریافت شده از عملیات hashing خود را که با نشانه خود JWT تطابق دارد، تایید کند. اگر نشانهها با هم تطابق داشته باشند، در نتیجه JWT معتبر است و API از یک منبع متعبر میآید. در غیر این صورت، JWT دریافت شده نامعتبر است و نمیتواند نمایانگر یک حمله احتمالی بر روی برنامه باشد. پس برنامه با تایید JWT، یک لایه امنیت به برنامه اضافه میکند.
نتیجه گیری
ما این که JWTها چه هستند، چگونه ساخته شده و تایید میشوند، و نحوه استفاده از آنها برای ایجاد امنیت بین برنامه و کاربرانش را دیدیم. این یک نقطه شروع خوب برای درک اصول JWTها بود.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید