JWT چیست آموزش استفاده از آن ( بروزرسانی )

JWT چیست آموزش استفاده از آن ( بروزرسانی )

JWT چیست آموزش استفاده از آن – کلمه jwt به معنای json web token می باشد که در هر پلتفرمی قابل استفاده است که برای Authorization تایید دسترسی کاربر به منابع مورد استفاده قرار می گیرد .

jwt از پروتکل oauth 2 بهره می برد که یک پروتکل استاندارد محسوب می شود ، یکی از نمونه های بارز آن توییتر است که از این نوع اعتبار سنجی استفاده می کند .

روش های معمولی زیادی برای تایید دسترسی کاربر وجود دارد مثل ذخیره نام کاربری و پسورد به صورت رمزگذاری شده در کوکی .

اما JWT یک راه بهتر و با امنیت بالا می باشد که در عین حال بسیار انعطاف پذیر تر می باشد و در پلتفرم های دیگر مثل android و ios مورد استفاده قرار می گیرد .


JWT چگونه کار می کند ؟

JWT چیست آموزش استفاده از آن

بخش ساخت توکن

همانطور که در تصویر بالا مشاهده می کنید از 3 بخش تشکیل می شود :

1- Header : این بخش مشخص کننده الگوریتم رمزگذاری است و اطلاعاتی در مورد آن می دهد
2- Payload : داده هایی که می خواهیم ذخیره کنیم و بعدا از آن استفاده کنیم ، مثل نام کاربری و ایمیل
3- Signature : این بخش از ادغام بخش 1 و 2 به صورت رمزگذاری base64 است و secret key است .
در واقع secret key باید یک رمز پیچیده باشد تا باعث بالا رفتن امنیت رمزنگاری شود .

این خیلی مهم است که secret key در اختیار افراد غیر قابل اعتماد قرار نگیرد در صورتی که قرار گیرد احتمال پیدا کردن توکن بدون نیاز به دسترسی وبسایت بالا رفته و امنیت پایین می آید .

در پایان با استفاده از تابع hash_hmac رمزنگاری را انجام می دهیم . اکنون توکنی دریافت می کنیم شبیه به :

eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6IjEyMzQ1Njc4OTAiLCJ1c2VybmFtZSI6ImFybWFuMDEifQ.qsLOFsFLyM__b6biNKkwMBJpNxhnQuD23vDyKMBeXvbMNx9otLrbHPySp8Nsvnpu

این توکن به این شکل رمزگذاری شده :

Header . Payload . Signature


تایید توکن ساخت شده JWT

پس از ساخت توکن در کوکی ذخیره می شود و هر وقت که کاربر بخواهد به منبعی مثل پروفایل خود برود توکن آن به سرور فرستاده می شود تا مورد بررسی قرار گیرد .

اکنون بخش اول توکن بالا یعنی header را بخواهیم با تابع base64_decode به رشته معمولی برگردانیم به این شکل می شود :

echo base64_decode("eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9"); // {"alg":"HS384","typ":"JWT"}


همچنین بخش 2 یعنی payload :

echo base64_decode("eyJlbWFpbCI6IjEyMzQ1Njc4OTAiLCJ1c2VybmFtZSI6ImFybWFuMDEifQ");// {"email":"1234567890","username":"arman01"}


پس سرور می آید توکن فرستاده شده کاربر را به طور موقت در متغیر ذخیره می کند تا بررسی کند که آیا معتبر هست یا خیر . بنابراین با 2 تکه ای که بدست آمده و secret key رمزگذاری می کند تا ببیند که آیا این توکنی که کاربر فرستاده با توکن خود همخوانی دارد یا خیر .

در صورتی که یکی باشد امکان دسترسی به کاربر داده می شود در غیر اینصورت پیغام :

Signature verification failed

می دهد .

ساخت و تایید jwt به صورت عملی

ساخت jwt

برای شروع کار ابتدا کتابخانه مخصوص PHP را با composer به پروژه خود اضافه نمایید :

composer require firebase/php-jwt

اکنون کد زیر را اضافه کنید ( توضیحات در پایین کد ) :

require_once "vendor/autoload.php";
 
use \Firebase\JWT\JWT;
use Firebase\JWT\Key;
 
$secret_key = "ELITE_CODERS_SECRET_KEY";
 
$day = 1;
$current_time_base_second = time();
$nbf = $current_time_base_second + 0;
$exp = $current_time_base_second + 86400 * $day;
 
$payload = array(
    "iss" => "https://rapidcode.ir",
    "aud" => "http://rapidcode.io",
    "iat" => $current_time_base_second, 
    "nbf" => $nbf, 
    "exp" => $exp,
    "data" => array( 
        "email" => "info@rapidcode.ir",
        "exp_time" => $exp,
        "readable_time" => date("Y/m/d H:i:s" , $exp)
    )
);
 
try{
    $jwt = JWT::encode($payload , $secret_key , "HS384");
    echo ($jwt . "\n\n");

    $data = JWT::decode($jwt , new Key($secret_key , "HS384"));
    var_dump($data);
 
}catch(Exception $e){
    echo $e->getMessage();
}

لاین 6 : رمز مخفی یا secret key تاکید می شود که نباید در اختیار هر کسی قرار گیرد . یک رمز پیچیده برای این بخش در نظر بگیرید .

لاین 14 : این که توکن را چه وبسایتی ساخته و تایید می کند
لاین 15 : در صورتی که چندین دامنه مرتبط با یکدیگر داشته باشیم و بخواهیم برای دامنه rapidcode.io از دامنه rapidcode.ir استفاده کنیم
لاین 16 : زمان ساخت توکن بر اساس timestamp
لاین 17 : اینکه پس از ساخت تا چه مدت بعد توکن قابل استفاده نباشد .
لاین 18 : توکن تا چه زمانی معتبر باشد از آنجایی که در لاین 11 برای 1 روز تنظیم کردیم .
لاین 19 : داده هایی که متناسب با پروژه مان استفاده می کنیم مثلا ایمیل یا نام کاربری ، همچنین چند داده اضافی هم می توانیم داشته باشیم که اختیاری است .


لاین 27 : با تابع encode که متعلق به کلاس JWT است توکن را می سازیم این تابع دارای 3 ورودی است :

1- payload : داده هایی که مرتبط با کاربر است و بعدا مورد استفاده مان قرار می گیرید
2- secret key : رمز مخفی برای جلوگیری از پیداکردن الگوریتم ساخت توکن
3- الگوریتم رمزنگاری : پیشفرض HS256 است اما می تواند فرق داشته باشد ( اختیاری )

تایید و رمزگشایی توکن JWT

تابع JWT::decode دو کاربرد داره که هم تایید می کند که توکن معتبر است و هم داده را از توکن بیرون می کشد و به ما برمی گرداند .
نمونه آن در کد بالا می باشد .

این تابع دارای 2 ورودی ( اجباری ) است .

در بروزرسانی جدید با کمک کلاس Key ورودی دوم را می دهیم . ( 15 خرداد 1401 )

1- token : همان توکنی که کاربر در هر بار استفاده از منابع به سرور می فرستد
2- key : همان secret key + الگوریتم رمزنگاری در صورتی که ورودی دوم JWT::encode را وارد نکردید HS256 بدهید در صورتی که الگوریتم دیگری مثل HS384 داده اید همان را وارد کنید .

زمانی که با خطایی مرتبط با توکن مواجه نشویم و بتوانیم به داده استخراج شده از توکن کاربر دسترسی پیدا کنیم یعنی رمزنگاری را خود سرور انجام داده و معتبر است .

تست و خطای jwt

برای اینکه مطمئن شویم برنامه به درستی کار می کند به صورت دستی تغییری در توکن بدهید مثلا چند کاراکتر به توکن اضافه کنید .

حالا اگر خطایی دریافت کردید نشان دهنده این است که سرور متوجه شده که این توکن نامعتبر است و سرور نقشی در ساخت آن نداشته . خطای زیر نشان دهنده ی همین است :

Signature verification failed

ارسال نظر

جهت استفاده از کد حتما از تگ pre استفاده نمایید .

لیست نظرات

  1. Dude
    Dude

    سلام. واسه دیکود کردن توکن, شما به صورت دستی توکن وارد کردید ولی واسه دریافت توکن و دیکود کردن از چه روشی استفاده میشه کرد؟ من از روش پایین استفاده میکنم ولی خطا میده؟

    require_once "vendor/autoload.php";
     
    use \Firebase\JWT\JWT;
    
     $data = json_decode(file_get_contents("php://input"));
    
    $secret_key = "ELITE_CODERS_SECRET_KEY";
    
    $jwt=isset($data ->jwt) ? $data->jwt : "";
    
    if($jwt){
     
        try {
     
            $decoded = JWT::decode($jwt, $secret_key, array('HS384'));
    
            echo json_encode(array(
                "message" => "Access granted: ".$jwt,
                "error" => $e->getMessage()
            ));
     
        }catch (Exception $e){
     
        http_response_code(401);
     
        echo json_encode(array(
            "message" => "Access denied.",
            "error" => $e->getMessage()
        ));
    }
     }
    
    ارور زیر ===> Wrong number of segments
    14 خرداد 1401 | 22:16:13
  • حسین باقری
    حسین باقری

    درود ، خیلی ممنونم بابت نظر تون این کتابخانه بروزرسانی شده و دلیل خطا تون هم اینه که برای متود decode ورودی دوم باید ادغام secret key و نوع رمزنگاری در کلاس Key هست . مقاله رو بروز کردم . اما پیشنهاد می شه قبل از استفاده از php://input که ورودی های raw یا همون json رو هم می تونه بگیره به صورت دستی توکن رو بسازید و به متود decode بدید بعد از این که مطمئن شدید به درستی کار می کنه از php://input استفاده کنید .

    15 خرداد 1401 | 14:25:48
    • Dude
      Dude

      ممنون بابت راهنمایی. بله تغییرات انجام دادم و توکن هم به صورت دستی وارد کردم و توکن تایید شد. ولی زمانی که توکن به صورت دستی وارد نمی شه خطا میده. نوع خطا ==> Wrong number of segments

      15 خرداد 1401 | 19:48:29
      • حسین باقری
        حسین باقری

        احتمالا داده ای که برای decode از php://input وارد می کنید با داده دستی فرق می کنه کد زیر رو در پروژه تون اضافه کنید تا تمامی اطلاعاتی رو لاگ کنید و مشخص بشه که داده وارد شده چه ساختاری داره

        file_put_contents(__DIR__ . "/logger.txt" , var_export(file_get_contents("php://input") , true))
        
        15 خرداد 1401 | 20:46:51
        • Dude
          Dude

          تنها داده ای که دریافت میشه عدد 2 یا ' ' هستش. نمیدونم دلیلش چیه؟؟ require_once 'vendor\autoload.php'; use Firebase\JWT\JWT; use Firebase\JWT\Key; $data =file_put_contents(__DIR__ . "/logger.txt" , var_export(file_get_contents("php://input") ,true)); echo $data; $jwt=isset($data ->jwt) ? $data->jwt : ""; try{ $secret_key = "ELITE_CODERS_SECRET_KEY"; $decoded = JWT::decode($jwt , new Key($secret_key , "HS384")); echo json_encode($decoded); }catch(Exception $e){ echo $e->getMessage(); }

          15 خرداد 1401 | 21:59:17
        • حسین باقری
          حسین باقری

          اگر داده ای که دارید ارسال می کنید از فرم داره ارسال میشه با استفاده از POST_$ و GET_$ قابل دریافت البته با توجه به attribute به نام method باید استفاده بشه اما اگر داده ای که فرستاده می شه به صورت json هست همون php://input کافیه .

          16 خرداد 1401 | 12:26:30
  • محمود رنجبر نورآبادی
    محمود رنجبر نورآبادی

    سلام مهندس باقری یه مثال از لاگین کاربران با jwt می تونید بفرستید به ایمیل من سپاس از راهنمایی تون موفق باشید

    01 اسفند 1400 | 10:23:07
    • حسین باقری
      حسین باقری

      دورد ، بله کد زیر به کار میاد همچنین آموزش ساخت پنل کاربری در php هم کاربردی هست برای این موضوع .

      require_once "vendor/autoload.php";
       
      use \Firebase\JWT\JWT;
       
      $secret_key = "ELITE_CODERS_SECRET_KEY";
       
      $day = 1;
      $current_time_base_second = time();
      $nbf = $current_time_base_second + 5;
      $exp = $current_time_base_second + 86400 * $day;
       
      setcookie("user_token" , "arman.15478e9x6g" , $exp);
      $payload = array(
          "iss" => "https://rapidcode.ir",
          "aud" => "http://rapidcode.io",
          "iat" => $current_time_base_second, 
          "nbf" => $nbf, 
          "exp" => $exp,
          "data" => array( 
      		"user_id" => "x",
      		"username" => "x",
              "email" => "info@rapidcode.ir",
              "exp_time" => $exp,
              "readable_time" => date("Y/m/d H:i:s" , $exp)
          )
      );
      
      try{
          $user_jwt = JWT::encode($payload , $secret_key , "HS384");
       
          echo $user_jwt; // توکن اعتبار سنجی کاربر
       
      }catch(Exception $e){
          echo $e->getMessage();
      }
      
      05 اسفند 1400 | 12:39:27
    contact us

    انجام انواع پروژه های وب


    ( فروشگاهی ، خبری ، رزرواسیون ، وردپرس ، حل مشکلات وردپرسی )

    شماره تماس و واتساپ : 09398554859