اعتبار سنجی OAUTH 2. 0 دسترسی به NGINX و NGINX PLUS

ساخت وبلاگ

گزینه های زیادی برای تأیید اعتبار تماس های API وجود دارد ، از گواهینامه های مشتری X. 509 گرفته تا تأیید اعتبار HTTP. با این حال ، در سالهای اخیر ، یک استاندارد de facto در قالب نشانه های دسترسی OAUTH 2. 0 پدید آمده است. این اعتبار تأیید اعتبار از مشتری به سرور API منتقل می شود و به طور معمول به عنوان هدر HTTP حمل می شود.

OAUTH 2. 0 ، با این حال ، پیچ و خم استانداردهای اتصال دهنده است. فرآیندهای صدور ، ارائه و اعتبارسنجی جریان تأیید اعتبار OAUTH 2. 0 اغلب به چندین استاندارد مرتبط متکی است. در زمان نوشتن ، هشت استاندارد OAUTH 2. 0 وجود دارد ، و نشانه های دسترسی یک مورد در نقطه است ، زیرا مشخصات هسته OAUTH 2. 0 (RFC 6749) فرمی را برای نشانه های دسترسی مشخص نمی کند. در دنیای واقعی ، دو قالب در استفاده مشترک وجود دارد:

  • Json Web Token (JWT) همانطور که توسط RFC 7519 تعریف شده است
  • نشانه های مات که کمی بیشتر از یک شناسه منحصر به فرد برای یک مشتری معتبر هستند

پس از تأیید اعتبار ، مشتری با هر درخواست HTTP برای دستیابی به منابع محافظت شده ، نشانه دسترسی خود را ارائه می دهد. اعتبار سنجی نشانه دسترسی برای اطمینان از صادر شده توسط یک ارائه دهنده هویت قابل اعتماد (IDP) و اینکه منقضی نشده است ، لازم است. از آنجا که IDP ها به صورت رمزنگاری JWT هایی را که صادر می کنند امضا می کنند ، JWT ها را می توان "آفلاین" بدون وابستگی به زمان اجرا به IDP تأیید کرد. به طور معمول ، JWT همچنین شامل تاریخ انقضا است که می تواند نیز بررسی شود. ماژول nginx plus auth_jwt اعتبار سنجی JWT آفلاین را انجام می دهد.

از طرف دیگر ، نشانه های مات باید با ارسال آنها به آوارگان صادر شده ، تأیید شوند. با این حال ، این مزیت دارد که می توان چنین نشانه هایی را توسط IDP ابطال کرد ، به عنوان مثال به عنوان بخشی از یک عملیات جهانی ورود ، بدون اینکه جلسات قبلاً وارد شده باشد - هنوز هم فعال است. ورود جهانی نیز ممکن است اعتبار JWT ها را با IDP ضروری کند.

در این وبلاگ توضیح می دهیم که چگونه NGINX و NGINX PLUS می توانند به عنوان یک طرف OAUTH 2. 0 با تکیه عمل کنند ، برای اعتبار سنجی و فقط درخواست های پروکسی که روند اعتبارسنجی را تصویب می کنند ، به IDP ارسال می کنند. ما در مورد مزایای مختلف استفاده از NGINX و NGINX PLUS برای این کار بحث می کنیم و چگونه می توان تجربه کاربر را با ذخیره پاسخ های اعتبار سنجی برای مدت کوتاهی بهبود بخشید. برای Nginx Plus ، ما همچنین نشان می دهیم که چگونه می توان حافظه پنهان را در یک خوشه از نمونه های NGINX Plus توزیع کرد ، با به روز کردن فروشگاه Value Key - با ماژول JavaScript ، همانطور که در Nginx Plus R18 معرفی شده است.

به جز در مواردی که ذکر شد ، اطلاعات موجود در این وبلاگ مربوط به منبع باز NGINX و NGINX PLUS است. ارجاع به Nginx Plus فقط مربوط به آن محصول است.

درون نگری

روش استاندارد برای اعتبار سنجی نشانه های دسترسی با IDP ، درون نگری Token نامیده می شود. RFC 7662 ، OAUTH 2. 0 TOKEN Introspection ، اکنون یک استاندارد بسیار پشتیبانی شده است که یک رابط JSON/REST را توصیف می کند که یک طرف متکی از آن برای ارائه یک نشانه به IDP استفاده می کند و ساختار پاسخ را توصیف می کند. این توسط بسیاری از فروشندگان پیشرو در IDP و ارائه دهندگان ابر پشتیبانی می شود.

صرف نظر از اینکه از کدام قالب توکن استفاده می شود ، انجام اعتبار سنجی در هر سرویس پس زمینه یا برنامه در بسیاری از کد های تکراری و پردازش غیر ضروری است. شرایط مختلف خطای و موارد لبه باید مورد توجه قرار گیرد ، و انجام این کار در هر سرویس باطن ، دستور العمل ناسازگاری در اجرای و در نتیجه یک تجربه کاربر غیرقابل پیش بینی است. در نظر بگیرید که چگونه هر سرویس پس زمینه ممکن است شرایط خطای زیر را اداره کند:

 

  • نشانه دسترسی از دست رفته
  • نشانه دسترسی بسیار بزرگ
  • شخصیت های نامعتبر یا غیر منتظره در نشانه دسترسی
  • توکن های دسترسی چندگانه ارائه شده است
  • ساعت در خدمات پس زمینه

 

با استفاده از ماژول nginx auth_request برای اعتبارسنجی نشانه ها

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

 

  • درخواست ها فقط هنگامی که مشتری یک نشانه معتبر ارائه داده است ، به خدمات باطن می رسند
  • خدمات باطن موجود می تواند بدون نیاز به تغییر کد با نشانه های دسترسی محافظت شود
  • فقط نمونه nginx (همه برنامه ها) باید در IDP ثبت شود
  • رفتار برای هر شرایط خطا ، از جمله نشانه های گمشده یا نامعتبر سازگار است

 

با استفاده از NGINX به عنوان یک پروکسی معکوس برای یک یا چند برنامه ، می توانیم از ماژول Auth_Request استفاده کنیم تا قبل از ارائه درخواست به پس زمینه ، یک تماس API را به یک IDP انجام دهیم. همانطور که در یک لحظه خواهیم دید ، راه حل زیر دارای یک نقص اساسی است ، اما عملکرد اصلی ماژول Auth_Request را معرفی می کند ، که ما در بخش های بعدی آن را گسترش خواهیم داد.

دستورالعمل AUTH_REQUEST (خط 5) مکان دستیابی به تماس های API را مشخص می کند. مجوز به پس زمینه (خط 6) فقط درصورتی اتفاق می افتد که پاسخ Auth_Request موفقیت آمیز باشد. مکان Auth_Request در خط 9 تعریف شده است. برای جلوگیری از دسترسی مستقیم مشتری های خارجی به آن ، به عنوان داخلی مشخص شده است.

خطوط 11-14 ویژگی های مختلف درخواست را به گونه ای تعریف می کند که مطابق با قالب درخواست درون نگری باشد. توجه داشته باشید که نشانه دسترسی ارسال شده در درخواست درونگرا ، مؤلفه ای از بدنه است که در خط 14 تعریف شده است. در اینجا توکن = $ http_apikey نشان می دهد که مشتری باید نشانه دسترسی را در عنوان درخواست Apikey ارائه دهد. البته ، نشانه دسترسی را می توان در هر ویژگی درخواست ارائه داد ، در این صورت ما از یک متغیر NGINX متفاوت استفاده می کنیم.

گسترش auth_request با ماژول javaScript nginx

همانطور که گفته شد ، استفاده از ماژول auth_request از این طریق یک راه حل کامل نیست. ماژول Auth_Request از کدهای وضعیت HTTP برای تعیین موفقیت استفاده می کند (2 xx = خوب ، 4 xx = بد). با این حال ، پاسخ های درون نگری OAUTH 2. 0 موفقیت یا عدم موفقیت را در یک شیء JSON رمزگذاری می کند و کد وضعیت HTTP 200 (OK) را در هر دو مورد باز می گرداند.

آنچه ما به آن نیاز داریم یک تجزیه کننده JSON برای تبدیل پاسخ درونگرا IDP به کد وضعیت HTTP مناسب است تا ماژول Auth_Request بتواند آن پاسخ را به درستی تفسیر کند.

خوشبختانه ، JSON PARSING یک کار بی اهمیت برای ماژول Nginx JavaScript (NJS) است. بنابراین به جای تعریف یک بلوک موقعیت مکانی برای انجام درخواست درون گرایی توکن ، ما به ماژول Auth_Request می گوییم که یک عملکرد JavaScript را فراخوانی کند.

[ویرایشگر - این پست یکی از چندین مورد است که موارد استفاده را برای ماژول Nginx JavaScript کشف می کند. برای یک لیست کامل ، به موارد استفاده برای ماژول Nginx JavaScript مراجعه کنید.

کد موجود در این بخش برای استفاده از دستورالعمل JS_IMPORT ، که جایگزین دستورالعمل JS_INCLUDE در NGINX PLUS R23 و بعد است ، به روز شده است. برای اطلاعات بیشتر ، به مستندات مرجع برای ماژول JavaScript Nginx مراجعه کنید - بخش پیکربندی مثال نحو صحیح برای پیکربندی NGINX و پرونده های JavaScript را نشان می دهد.]

توجه: این راه حل نیاز به ماژول JavaScript دارد که به عنوان یک ماژول پویا با دستورالعمل LOAD_MODULE در nginx. conf بارگیری شود. برای دستورالعمل ، به راهنمای مدیر Nginx Plus مراجعه کنید.

دستورالعمل JS_CONTENT در خط 13 یک عملکرد JavaScript ، IntrospectAccessToken را به عنوان کنترل کننده Auth_Request مشخص می کند. عملکرد کنترل کننده در oauth2. js تعریف شده است:

توجه کنید که عملکرد IntrospectAccessToken یک زیر مجموعه HTTP (خط 2) را به یک مکان دیگر ( /OAUTH2_SEND_REQUEST) تبدیل می کند که در قطعه پیکربندی زیر تعریف شده است. کد JavaScript سپس پاسخ (خط 5) را تجزیه می کند و کد وضعیت مناسب را بر اساس مقدار قسمت فعال به ماژول Auth_Request ارسال می کند. نشانه های معتبر (فعال) بازگشت HTTP 204 (بدون محتوا) (اما موفقیت) و نشانه های نامعتبر HTTP 403 (ممنوع) را برمی گردانند. شرایط خطا بازگشت HTTP 401 (غیرمجاز) به طوری که خطاها را می توان از نشانه های نامعتبر متمایز کرد.

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

مکان هدف Subrequest که در خط 2 تعریف شده است بسیار شبیه به پیکربندی اصلی Auth_Request ما است.

تمام پیکربندی ها برای ساخت درخواست درونگرایی توکن در مکان /_oauth2_send_request موجود است. احراز هویت (خط 19) ، نشانه دسترسی (خط 21) و URL برای نقطه پایانی درونگرایی Token (خط 22) به طور معمول تنها موارد پیکربندی لازم است. احراز هویت برای IDP لازم است تا درخواست های درون نگری را از این نمونه NGINX بپذیرد. مشخصات درون نگری OAUTH 2. 0 تأیید اعتبار را تأیید می کند ، اما روش را مشخص نمی کند. در این مثال ، ما در هدر مجوز از یک نشانه تحمل استفاده می کنیم.

با استفاده از این پیکربندی ، هنگامی که NGINX درخواست دریافت می کند ، آن را به ماژول JavaScript منتقل می کند ، که باعث می شود یک درخواست درون نگری در برابر IDP باشد. پاسخ از IDP مورد بازرسی قرار می گیرد ، و در صورت صحت قسمت فعال ، تأیید اعتبار موفقیت آمیز تلقی می شود. این راه حل یک روش جمع و جور و کارآمد برای انجام درونگرایی OAUTH 2. 0 با NGINX است و به راحتی می تواند برای سایر API های احراز هویت سازگار باشد.

اما ما کاملاً تمام نشده است. به طور کلی بزرگترین چالش با درون نگری توکن این است که به هر درخواست HTTP تأخیر می افزاید. این مسئله می تواند به یک مسئله مهم تبدیل شود که IDP مورد نظر یک راه حل میزبان یا ارائه دهنده ابر باشد. NGINX و NGINX PLUS می توانند با ذخیره پاسخ های درون نگر ، بهینه سازی را برای این اشکال ارائه دهند.

بهینه سازی 1: ذخیره توسط nginx

Introspection OAUTH 2. 0 توسط IDP در نقطه انتهایی JSON/REST ارائه می شود ، بنابراین پاسخ استاندارد یک بدنه JSON با وضعیت HTTP 200 است. هنگامی که این پاسخ در برابر نشانه دسترسی مهم است ، بسیار قابل ذخیره می شود.

NGINX را می توان برای ذخیره یک نسخه از پاسخ درون نگری برای هر نشانه دسترسی تنظیم کرد تا دفعه بعدی که همان نشانه دسترسی ارائه می شود ، Nginx به جای برقراری تماس API به IDP ، پاسخ درونگرایی ذخیره شده را ارائه می دهد. این به شدت تأخیر کلی را برای درخواست های بعدی بهبود می بخشد. ما می توانیم کنترل کنیم که چه مدت از پاسخ های ذخیره شده استفاده می شود ، تا خطر پذیرش یک نشانه دسترسی منقضی شده یا اخیراً ابطال شده را کاهش دهیم. به عنوان مثال ، اگر یک مشتری API به طور معمول در مدت زمان کوتاهی از چندین تماس API پشت سر بگذارد ، اعتبار حافظه نهان 10 ثانیه ممکن است برای ارائه یک پیشرفت قابل اندازه گیری در تجربه کاربر کافی باشد.

ذخیره سازی با مشخص کردن ذخیره سازی آن - یک دایرکتوری روی دیسک برای حافظه نهان (پاسخ های درون نگری) و یک منطقه حافظه مشترک برای کلیدها (به نشانه های دسترسی) فعال می شود.

دستورالعمل proxy_cache_path ذخیره سازی لازم را اختصاص می دهد:/var/cache/nginx/oauth برای پاسخ های درون نگری و یک منطقه حافظه به نام token_responses برای کلیدها. در متن HTTP پیکربندی شده است و بنابراین در خارج از سرور و بلوک های مکان ظاهر می شود. ذخیره خود سپس در داخل بلوک موقعیت مکانی که پاسخ های درون گرایانه توکن پردازش می شوند ، فعال می شوند:

ذخیره سازی برای این مکان با دستورالعمل proxy_cache (خط 26) فعال می شود. به طور پیش فرض Nginx Caches بر اساس URI اما در مورد ما می خواهیم پاسخ را بر اساس نشانه دسترسی ارائه شده در عنوان درخواست Apikey (خط 27) ذخیره کنیم.

در خط 28 ما از دستورالعمل proxy_cache_lock استفاده می کنیم تا به Nginx بگوییم که اگر درخواست های همزمان با همان کلید حافظه نهان وارد شوند ، باید صبر کنیم تا اولین درخواست قبل از پاسخ به دیگران ، حافظه نهان را جمع کند. دستورالعمل proxy_cache_valid (خط 29) به nginx می گوید که چه مدت می تواند پاسخ درونگرایی را ذخیره کند. بدون این دستورالعمل NGINX زمان ذخیره سازی از هدرهای کنترل حافظه نهان را که توسط IDP ارسال شده است تعیین می کند. با این حال ، اینها همیشه قابل اعتماد نیستند ، به همین دلیل ما همچنین به NGINX می گوییم که هدرهایی را که در غیر این صورت می تواند بر نحوه پاسخ حافظه نهان تأثیر بگذارد ، نادیده بگیریم (خط 30).

با فعال کردن ذخیره در حال حاضر ، مشتری که یک نشانه دسترسی را ارائه می دهد ، فقط هزینه تأخیر در درخواست توکن را در هر 10 ثانیه یک بار متحمل می کند.

بهینه سازی 2: ذخیره سازی توزیع شده با Nginx Plus

ترکیب ذخیره سازی محتوا با درون نگری توکن روشی بسیار مؤثر برای بهبود عملکرد کلی برنامه با تأثیر ناچیز بر امنیت است. با این حال ، اگر NGINX به روشی توزیع شده مستقر شود - به عنوان مثال ، در چندین مراکز داده ، سیستم عامل های ابری یا یک خوشه فعال فعال - سپس پاسخ های درون نگر توکن ذخیره شده فقط برای نمونه NGINX که درخواست درون نگری را انجام می دهد در دسترس است.

با NGINX PLUS می توانیم از ماژول KeyVal - یک فروشگاه کلیدی در نظر بگیریم - برای ذخیره پاسخ های درون نگرانه. علاوه بر این ، ما همچنین می توانیم با استفاده از ماژول Zone_Sync ، این پاسخ ها را در یک خوشه از موارد Nginx Plus همگام سازی کنیم. این بدان معناست که مهم نیست که کدام نمونه Nginx Plus درخواست درون گرایی توکن را انجام داده است ، پاسخ در همه موارد Nginx Plus در خوشه در دسترس است.

توجه: پیکربندی ماژول Zone_Sync برای به اشتراک گذاری حالت اجرا خارج از محدوده این وبلاگ است. برای کسب اطلاعات بیشتر در مورد به اشتراک گذاری وضعیت در یک خوشه Nginx Plus ، به راهنمای مدیر NGINX Plus مراجعه کنید.

در NGINX PLUS R18 و بعد از آن ، می توان با اصلاح متغیری که در دستورالعمل KeyVal اعلام شده است ، فروشگاه Value Key - Value به روز شود. از آنجا که ماژول JavaScript به همه متغیرهای NGINX دسترسی دارد ، این امکان را فراهم می کند تا پاسخ های درون نگری در هنگام پردازش پاسخ در فروشگاه ارزش کلیدی جمع شوند.

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

توجه داشته باشید که با پارامتر Timeout به دستورالعمل KeyVal_Zone ، ما همان دوره اعتبار 10 ثانیه ای را برای پاسخ های ذخیره شده به عنوان خط 29 از Auth_Request_cache. conf مشخص می کنیم ، به طوری که هر یک از اعضای خوشه Nginx Plus به طور مستقل هنگام انقضاء پاسخ را از بین می برند. خط 2 جفت کلید Value را برای هر ورودی مشخص می کند: کلید این که نشانه دسترسی در عنوان درخواست Apikey است ، و مقدار پاسخ درونگرایی است که توسط متغیر $ token_data ارزیابی می شود.

اکنون ، برای هر درخواستی که شامل یک عنوان درخواست apikey باشد ، متغیر $ token_data در صورت وجود پاسخ درون نگری توکن قبلی است. بنابراین ما کد JavaScript را به روز می کنیم تا بررسی کنیم که آیا در حال حاضر یک پاسخ درونگرایی نشان می دهیم.

خط 2 آزمایش می کند که آیا در حال حاضر یک فروشگاه کلیدی ارزش برای این نشانه دسترسی وجود دارد. از آنجا که دو مسیر وجود دارد که با استفاده از آن می توان یک پاسخ درونگرا (از فروشگاه کلیدی - یا از یک پاسخ درون نگری) بدست آورد ، ما منطق اعتبارسنجی را به عملکرد جداگانه زیر ، TokenResult منتقل می کنیم:

اکنون ، هر پاسخ درونگرایی به فروشگاه کلیدی ذخیره می شود و در بین سایر اعضای خوشه Nginx Plus هماهنگ می شود. مثال زیر یک درخواست HTTP ساده را با یک نشانه دسترسی معتبر نشان می دهد و به دنبال آن یک پرس و جو به API Nginx Plus برای نشان دادن محتوای فروشگاه ارزش کلید نشان می دهد.

$ curl -IH "apikey: tQ7AfuEFvI1yI-XNPNhjT38vg_reGkpDFA" http://localhost/ HTTP/1.1 200 OK Date: Wed, 24 Apr 2019 17:41:34 GMT Content-Type: application/json Content-Length: 612 $ curl http://localhost/api/4/http/keyvals/access_tokens ">

توجه داشته باشید که فروشگاه Value Key - از خود از فرمت JSON استفاده می کند ، بنابراین پاسخ درونگرایی توکن به طور خودکار فرار می کند که برای علائم نقل قول اعمال می شود.

بهینه سازی 3: استخراج ویژگی ها از پاسخ درونگرایی

یک قابلیت مفید از درونگرایی OAUTH 2. 0 این است که پاسخ می تواند علاوه بر وضعیت فعال آن ، اطلاعات مربوط به نشانه را شامل شود. چنین اطلاعاتی شامل تاریخ انقضا توکن و ویژگی های کاربر مرتبط است: نام کاربری ، آدرس ایمیل و غیره.

این اطلاعات اضافی می تواند بسیار مفید باشد. می توان آن را وارد کرد ، برای اجرای سیاستهای کنترل دسترسی ریز دانه استفاده شده یا برای برنامه های باطن ارائه شده است. ما می توانیم با ارسال آنها به عنوان عنوان های پاسخ اضافی با پاسخ موفق (HTTP 204) ، هر یک از این ویژگی ها را به ماژول Auth_Request صادر کنیم.

ما بیش از هر ویژگی از پاسخ درونگرا (خط 23) تکرار می کنیم و آن را به عنوان یک عنوان پاسخ به ماژول Auth_Request ارسال می کنیم. برای جلوگیری از درگیری با هدرهای پاسخ استاندارد (خط 26) ، هر نام هدر با نشانه پیشوند است. این هدرهای پاسخ اکنون می توانند به متغیرهای NGINX تبدیل شوند و به عنوان بخشی از پیکربندی منظم استفاده شوند.

در این مثال ، ما ویژگی نام کاربری را به یک متغیر جدید ، نام کاربری $ (خط 11) تبدیل می کنیم. دستورالعمل AUTH_REQUEST_SET ما را قادر می سازد تا زمینه پاسخ درونگرایی توکن را به متن درخواست فعلی صادر کنیم. عنوان پاسخ برای هر ویژگی (اضافه شده توسط کد JavaScript) به عنوان ویژگی $ sent_http_token_ در دسترس است. خط 12 سپس ارزش نام کاربری $ را به عنوان یک عنوان درخواست که در پس زمینه قرار دارد ، شامل می شود. ما می توانیم این پیکربندی را برای هر یک از ویژگی های برگشتی در پاسخ درونگرایی توکن تکرار کنیم.

پیکربندی تولید

نمونه های کد و پیکربندی فوق کاربردی هستند و برای آزمایش اثبات مفهوم یا سفارشی سازی برای یک مورد استفاده خاص مناسب هستند. برای استفاده از تولید ، ما به شدت استفاده از خطای اضافی ، ورود به سیستم و پیکربندی انعطاف پذیر را توصیه می کنیم. شما می توانید یک اجرای قوی تر و شفاف تر برای nginx و nginx plus در repo github ما پیدا کنید:

  • توکن OAUTH 2. 0 با NGINX (ذخیره دیسک)
  • Introspection OAUTH 2. 0 با Nginx Plus (حافظه پنهان ارزش کلید)

خلاصه

در این وبلاگ ما نشان داده ایم که چگونه می توان از ماژول nginx auth_request در رابطه با ماژول JavaScript برای انجام درون نگر OAUTH 2. 0 در درخواست های مشتری استفاده کرد. علاوه بر این ، ما آن محلول را با ذخیره سازی گسترش داده ایم و ویژگی هایی را از پاسخ درون نگری برای استفاده در پیکربندی Nginx استخراج کرده ایم.

ما همچنین توضیح دادیم که چگونه می توان از فروشگاه Value Value NGINX به علاوه به عنوان حافظه نهان توزیع شده برای پاسخ های درون نگر استفاده کرد ، مناسب برای استقرار تولید در یک خوشه از موارد Nginx Plus.

Introspection OAUTH 2. 0 را با Nginx Plus برای خودتان امتحان کنید-امروز 30 روز آزمایش رایگان خود را شروع کنید یا برای بحث در مورد موارد استفاده خود با ما تماس بگیرید.

فارکس کاران ایران...
ما را در سایت فارکس کاران ایران دنبال می کنید

برچسب : نویسنده : ديناروند فهيمه بازدید : <-PostHit-> تاريخ : يکشنبه 11 تير 1402 ساعت: 14:09