همانطور که میدانید، برای استفاده از درخواستهای API یا API Requests که نیازمند مجوز (Authorization) بر پایهی توکن هستند، توکنِ مربوطه باید همزمان با درخواست، ارسال شود. این توکن باید از طریق احراز هویت کاربر دریافت شود، سپس میتوان از توکنِ ایجاد شده در سایر درخواستها استفاده کرد. بارها دیدهام که افراد در نقشهای مختلف در تیم توسعه، اعم از برنامهنویس بکاند یا فرانتاند یا تسترها یا... هنگام بکارگیری این APIها در Postman، درگیری زیادی در احراز هویت، دریافت توکن و استفاده از آن دارند، به نحوی که زمان زیادی صرف احراز هویت با استفاده از نام کاربری و کلمه عبور، دریافت توکن و استفاده از آن در فراخوانی سایر درخواستها میشود.
در Postman قابلیتهایی وجود دارد که با استفاده از آنها میتوان این عمل را تسهیل و حتی خودکار کرد. در این نوشته ابتدا به نحوهی احراز هویت، دریافت مجوز و استفاده از آن در Postman میپردازیم، سپس سعی میکنیم با استفاده از قابلیتهای موجود، روند را تسهیل کنیم!
ابتدا به این نکته اشاره کنم که «احراز هویت بر پایهی توکن» احتملا جملهی دقیقی نباشد. آنچه مبتنی بر توکن است، مجوزها (Authorization) است و نه احراز هویت (Authentication). به شکل دقیقتر، هنگام احراز هویت کاربر با استفاده از نام کاربری و کلمهی عبور، یک توکن ایجاد میشود که مجوز دسترسی ما به سایر درخواستها (API requests) است.
با این تفاسیر، ابتدا نیاز است با ارسال نام کاربری و کلمه عبور به endpoint مربوطه و احراز هویت کاربر، توکن دریافت شود تا در فراخوانی سایر درخواستها بتوان از آن استفاده کرد. برای این منظور مراحل زیر در Postman اتفاق خواهد افتاد:
همانطور که ملاحظه میکنید، نام کاربری و کلمه عبور با فرمت JSON به endpoint مربوط به احراز هویت (در اینجا login) ارسال شده و access token و refresh token به عنوان پاسخ دریافت شده است.
با در اختیار داشتن توکن (access token)، میتوان نسبت به استفاده از آن برای مشخص کردن مجوز دسترسی در سایر درخواستها اقدام کرد. بنابراین در درخواستهای نیازمند مجوز، توکن دریافتی در مرحلهی قبل باید به همراه درخواستها ارسال شود. این مورد در تب Authorization، و برحسب نوع توکن (bearer، JWT یا...) مشخص میشود.
با توجه به اینکه توکنهای دریافتی منقضی میشوند، زمان زیادی برای دریافت توکن و استفاده از آن در درخواستها مورد نیاز خواهد بود. بهتر است به نحوی این فرایند تسهیل شود تا تمرکز هریک از اعضای تیم که قرار است از این APIها در Postman استفاده کنند، به جای دریافت و کپی کردن توکن هنگام ارسال یک درخواست به کار اصلی خود معطوف شود! در ادامه توضیح میدهم به چه صورت!
در Postman شما میتواند مجموعههای (collection) متفاوتی از درخواستهایی که نیاز به فراخوانی آنها در پروژهی خود دارید را ذخیره کنید. این امر فراخوانی درخواستها را تسهیل میکند و با یکبار ذخیرهی endpointها، متدها و اطلاعات ارسالی (در صورت نیاز) میتوانید بارها آنها را فراخوانی کنید. علاوه بر تعریف مجموعهها، شما میتوانید از پوشهبندی درخواستها نیز استفاده کنید.
شما درخواستهای خود را در قالب مجموعهها ذخیره کردهاید اما فراخوانی درخواستها ممکن است بسته به محیطی که در حال فراخوانی درخواست هستید، دارای تنظیمات متفاوتی باشد (محیط توسعه، تست، عملیاتی). مثلا محیط توسعه شما در مسیر http://127.0.0.1:5000 است اما محیط تست شما http://testserver:8080 است. یا مثلا نام کاربری و کلمه عبوری که در محیطهای مخلتف مورد استفاده قرار میگیرد متفاوت است. منطقی نیست شما تمامی درخواستها را برای محیطهای متفاوت بازتعریف کنید. Postman فکر اینجا را نیز کرده و به شما این امکان را میدهد تا درخواستهای خود را در محیطهای متفاوتی اجرا کنید! در یک محیط شما میتوانید متغیرهایی که معرف ویژگیهای خاص محیط شما هستند را (مانند آدرس سرور، نامهای کاربر، کلمههای عبور و...) را تعریف کنید.
پس از تعریف یک محیط، شما میتوانید از متغیرهایی که معرف هر محیط هستند در درخواستهای خود استفاده کنید. مثلا به جای استفادهی صریح از آدرس سرور از متغیری که برای این منظور تعریف شده است استفاده میکنیم:
به این ترتیب برای اجرای یک درخواست روی محیطهای متفاوت، صرفا کافی است محیط مورد نظر خود را انتخاب کنید تا درخواست با تنظیمات مورد نظر شما اجرا شود!
برای نام کاربری و کلمه عبور نیز به همین ترتیب، امکان استفاده از متغیرهای تعریف شده در محیط میسر است:
نام کاربری و کلمه عبور در متغیرهای محیطی تعریف شده است و هنگام ارسال درخواست احراز هویت، مقادیر این متغیرها ارسال میشوند. به این ترتیب هنگام ارسال یک درخواست در محیطهای مختلف، نیاز به تغییر نام کاربر و کلمهی عبور در درخواست نیست.
تا اینجای کار دیدیم چگونه احراز هویت مبتنی بر توکن را در Postman انجام دهیم و چگونه با استفاده از قابلیتهایی که Postman در اختیار ما میگذارد، امور روزمره را تسهیل کنیم! حال میخواهیم با استفاده از سایر امکانات Postman، کاری کنیم که نیازی نباشد بعد از هربار احراز هویت و دریافت توکن، آنرا به Authorization درخواستها اضافه کنیم!
برای این منظور میتوان از اسکریپتهای تست Postman استفاده کرد. این تستها با جاوااسکریپت نوشته میشوند و بعد از اجرای درخواست و دریافت پاسخ اجرا میشوند. تستها کارکردی فراتر از استفادهای که ما میخواهیم از آن بکنیم دارد، اما در اینجا میخواهیم هنگام احراز هویت، توکن دریافتی را در یک متغیر محیطی ذخیره کنیم تا هنگام ارسال درخواستها بتوانیم از آن متغیر استفاده کنیم. بنابراین یک تست به صورت زیر هنگام احراز هویت اجرا میکنیم:
در این تست، یک متغیر با نام auth_token را با توکن دریافتی از احراز هویت مقداردهی کردیم. حال میتوانیم در درخواستهایی که نیاز به مجوز دارند، از آن متغیر استفاده کنیم:
توجه شود که در مجموعهها امکان ارثبری در مجوزها وجود دارد. لذا میتوان متغیر را در سطح مجموعه به کار برد و برای درخواستها، مقدار Inherit auth from parent را انتخاب کرد!
تا اینجا دیدیم که چگونه میتوان با استفاده از یک تست و استفاده از متغیرهای محیطی، کاری کرد که بعد از احراز هویت کاربر، نیازی به کپی کردن توکن در سایر درخواستها نباشد! حالا میخواهیم پا را فراتر بگذاریم: میخواهیم هنگام ارسال یک درخواست، در صورتی که توکنی وجود نداشته باشد یا منقضی شده باشد، عمل احراز هویت و دریافت و استفاده از آن به شکل خودکار انجام شود! به این تریتب دیگر نیازی به احراز هویت به عنوان پیششرط ارسال درخواستهایی که نیازمند مجوز هستند نخواهیم داشت!
در Postman امکاناتی وجود دارد که این موضوع را برای ما ممکن میکند: Pre-request Scripts! این اسکریپت برخلاف تستها که بعد از ارسال درخواست و دریافت پاسخ اجرا میشدند، پیش از ارسال درخواست اجرا میشوند. با این تفاسیر کافی است اسکریپتی بنویسیم که چک کند در صورتی که توکن معتبری وجود ندارد، احراز هویت انجام و توکن دریافت شود سپس درخواست ارسال شود. یک نمونه اسکریپت که میتواند برای این منظور استفاده شود به صورت زیر است:
pm.sendRequest({ url: pm.environment.get("url") + '/check', method: 'GET', header: { 'Accept': 'application/json', 'Authorization': 'Bearer ' + pm.environment.get('auth_token') }, }, function (error, response) { if(!error){ if (response.code === 401) { pm.sendRequest({ url: pm.environment.get("url") + '/login', method: 'POST', header: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: { mode: 'raw', raw: JSON.stringify({ username: pm.environment.get("username"), password: pm.environment.get("password") }) } }, function (error, response) { if(!error) { var jsonData = response.json(); pm.environment.set("auth_token", jsonData.access_token); } else { console.log('LOGIN Err: ' + error); } }); } } else { console.log('CHECK Err: ' + error); } });
در این اسکریپت، ابتدا یک درخواست به یک endpoint با نام check ارسال میشود که وظیفهی آن بررسی معتبر بودن توکن است. در صورتیکه توکن معتبر وجود نداشته باشد، یک درخواست به endpoint با نام login ارسال میشود که وظیفهی آن احراز هویت کاربر با نام کاربر و کلمه عبور ارسالی و دریافت توکن و ذخیرهی آن در متغیر محلی مربوطه است.
این اسکریپت میتواند به عنوان یک Pre-request Scripts برای یک درخواست نوشته شود و یا روی یک مجموعه یا فولدرهای آن. طبیعتا درخواستهای ذیل یک مجموعه یا فولدر، Pre-request Scripts را به ارث خواهند برد.
توجه شود این اسکریپت صرفا یک اسکریپت نمونه است و ممکن است شما endpointی مانند check برای بررسی اعتبار یک توکن نداشته در اختیار نداشته باشید و نیاز باشد به روشهای دیگری وجود یک توکن معتبر را بررسی کنید. همچنین توجه کنید این روش منجر به افزایش تعداد درخواستهای ارسالی شما میشود (به دلیل فراخوانی check) اما به تجربه دیدهام در محیطهای توسعه و تست، این روش در نهایت باعث افزایش عملکرد و بهبود تجربه کاری میشود.
به این ترتیب دیگر نیاز به انجام احراز هویت نخواهد بود و با فراخوانی هر درخواست، احراز هویت (در صورت نیاز) مجددا انجام خواهد شد.