paint-brush
JWT آپ کی انٹرپرائز ایپ کو محفوظ بنانے کی کلید کیوں ہے - اور KumuluzEE آپ کا نیا بہترین دوست کیوں ہو سکتا ہےکی طرف سے@jesperancinha
نئی تاریخ

JWT آپ کی انٹرپرائز ایپ کو محفوظ بنانے کی کلید کیوں ہے - اور KumuluzEE آپ کا نیا بہترین دوست کیوں ہو سکتا ہے

کی طرف سے João Esperancinha40m2025/01/17
Read on Terminal Reader

بہت لمبا؛ پڑھنے کے لئے

'JWT' یا JavaScript آبجیکٹ نوٹیشن ویب ٹوکن ایک معیاری ہے جو [RFC7519] میں بیان کیا گیا ہے اس کی متعدد طریقوں سے تعریف کی جا سکتی ہے اور اسے دو فریقوں کے درمیان معلومات کی ترسیل کے لیے استعمال کیا جا سکتا ہے۔ اس مضمون میں، ہم دیکھیں گے کہ JWT کو ایک عام جاوا انٹرپرائز ایپلی کیشن میں کیسے ضم کیا جائے۔
featured image - JWT آپ کی انٹرپرائز ایپ کو محفوظ بنانے کی کلید کیوں ہے - اور KumuluzEE آپ کا نیا بہترین دوست کیوں ہو سکتا ہے
João Esperancinha HackerNoon profile picture
0-item

آج کل، ہمیں کارکردگی کے بارے میں زیادہ سے زیادہ خدشات ہیں، اور ساتھ ہی، ہم یہ جاننا چاہتے ہیں کہ نظام کس طرح تیزی سے اور قابل اعتماد طریقے سے بات چیت کر سکتے ہیں۔ کئی بار ہم معلومات بھیجنا چاہتے ہیں اور اسے زیادہ سے زیادہ خفیہ اور محفوظ رکھنا چاہتے ہیں۔ حساس ڈیٹا کو بعض اوقات ویب کے ذریعے عوامی طور پر بھی جانا چاہیے اور تار کے دوسرے سرے پر کارروائیوں کو متحرک کرنا چاہیے۔ زیادہ تر، ہم ایسی حرکتیں پیدا کرنا چاہتے ہیں جو ڈیٹا کی تبدیلی کا سبب بنیں۔ ان معاملات میں، ہم نہ صرف اپنے ڈیٹا کی حفاظت کو دیکھ رہے ہیں۔ ہم اس بات کو یقینی بنانا چاہتے ہیں کہ ہمارا ڈیٹا بھیجنے سے شروع ہونے والی کارروائیاں قابل اعتماد ہیں۔ ہم اپنے ڈیٹا کو کئی طریقوں سے محفوظ کر سکتے ہیں۔ عام طور پر، ہم ڈیٹا کو TLS (ٹرانسپورٹ لیئر سیکیورٹی) محفوظ کنکشن کے ذریعے بھیجتے ہیں۔ یہ اس بات کو یقینی بنائے گا کہ ہمارا ڈیٹا تار کے ذریعے انکرپٹ ہو جائے۔ ہم سرٹیفکیٹس کا استعمال دو فریقوں کے درمیان اعتماد کے رشتے بنانے اور اسے حاصل کرنے کے لیے کرتے ہیں۔ اس مضمون میں، میں JWT معیار پر بات کرنا چاہتا ہوں اور مزید دیکھنا چاہتا ہوں کہ ہم JWT ایک مشترکہ Enterprise ایپلی کیشن میں کیسے ضم کر سکتے ہیں۔ اس صورت میں، ہم KumuluzEE پر ایک نظر ڈالیں گے .آئیے کچھ بنیادی تصورات پر ایک نظر ڈالتے ہیں۔ JWT یا JSON ویب ٹوکن، یا اس سے بہتر، JavaScript آبجیکٹ نوٹیشن ویب ٹوکن، RFC7519 میں بیان کردہ ایک معیار ہے۔ یہ معیار، تمام RFC (تبصروں کی درخواست) کے معیارات کی طرح، IETF (انٹرنیٹ انجینئرنگ ٹاسک فورس) کے ذریعہ بیان کردہ، تحریری، اور شائع کیا گیا ہے۔ اس کی متعدد طریقوں سے تعریف کی جا سکتی ہے۔ عام طور پر، ہم کہہ سکتے ہیں کہ JWT دو فریقوں کے درمیان دعووں کو منتقل کرنے کی ایک کمپیکٹ، محفوظ شکل ہے۔ دعویٰ کیا ہے اس کو آسان بنانے کا ایک طریقہ بنیادی طور پر اسے نام/قدر کے جوڑے کے طور پر بیان کرنا ہے جس میں معلومات شامل ہیں۔ ہمیں اپنے انٹرنیٹ مواصلات کے چند اہم پہلوؤں کی ضمانت کے لیے اس معلومات کی ضرورت ہے۔ ہمیں اس بات کو یقینی بنانے کی ضرورت ہے کہ ہمیں جو معلومات موصول ہوتی ہیں اس کی توثیق ہوتی ہے اور پہلی صورت میں اس پر بھروسہ کیا جاتا ہے۔ پھر ہمیں اس کی توثیق کرنے کی ضرورت ہے۔ یہ بنیادی طور پر ہے۔ اسپرنگ بوٹ کا بڑے پیمانے پر استعمال کیا جا رہا ہے۔ کئی بار اسے بعض تنظیموں جیسے بینکوں اور دیگر مالیاتی تنظیموں کے ملکیتی سافٹ ویئر میں دوسرے نام سے بھی لپیٹ دیا جاتا ہے۔ ہماری مثال کے لیے، میں نے کچھ مختلف کرنے کا فیصلہ کیا۔ اسپرنگ بوٹ کے بجائے، ہم KumuluzEE کے ساتھ ایک مثال دیکھنے جا رہے ہیں۔ نقطہ یہ ہے کہ یہ شناخت کرنا ہے کہ JWT کیا ہے اور یہ کیسا لگتا ہے۔ جاوا انٹرپرائز ایپلی کیشنز بنیادی طور پر ایپلی کیشنز ہیں جو کسی ایپلیکیشن سرور میں تعینات کی جا سکتی ہیں یا ایمبیڈڈ سرور کے استعمال کے ذریعے خود چلائی جا سکتی ہیں۔ مثال کے طور پر، اسپرنگ بوٹ ایپلی کیشنز ایمبیڈڈ ٹامکیٹ سرور پر چلتی ہیں۔ اس مضمون میں، ہماری توجہ KumuluzEE پر رکھی جائے گی۔ اسپرنگ بوٹ کی طرح اس میں بھی ایمبیڈڈ سرور ہوتا ہے۔ سوائے اس کے کہ اس صورت میں اسے جیٹی کہا جاتا ہے۔ یہ CDI (Context Dependency Injection) فراہم کرنے کے لیے ویلڈ کے ساتھ استعمال کیا جاتا ہے۔ تمام Java EE اور Jakarta EE ٹیکنالوجی کے معیارات اس framework کے ساتھ مطابقت رکھتے ہیں۔

2. کیس کی مثال


مثال دینے کے لیے کہ JWT اپنی بنیادی شکل میں کیسے کام کرتا ہے، مجھے اسے پیش کرنے کا طریقہ سوچنا پڑا۔ بہترین مثالیں جہاں سیکیورٹی ایک تشویش کا باعث ہے وہ بینک ہیں۔ تاہم، یہ بتانے کے لیے کہ JWT کیسے کام کرتا ہے ایک پوری بینک درخواست بنانا وقت کا ضیاع ہوگا اور شاید بہت سارے تصورات اس میں شامل ہوں گے۔ اس کے بجائے، میں نے جو بنایا ہے وہ ایک بہت ہی آسان بینکنگ سسٹم ہے۔ ہماری بنیادی تشویش یہ بتانا ہے کہ ڈیٹا تار سے کیسے گزرتا ہے اور صارفین کو ہماری ایپلیکیشن کے مخصوص علاقوں تک کیسے رسائی حاصل ہوتی ہے۔ میں TLS پر بھی بات نہیں کروں گا یا ہم تار کے ذریعے خفیہ کردہ معلومات کیسے بھیج سکتے ہیں۔ ہم اپنی توجہ JWT پر اس کی خالص ترین شکل میں رکھیں گے۔ ہمارا کیس ایک بینکنگ سسٹم ہے جسے فطرت اور ماحول کا دفاع کرنے والا گروپ استعمال کرتا ہے۔ یہ صرف یہ دکھانے کا ایک تفریحی طریقہ ہے کہ JWT کیسے کام کرتا ہے۔ اس لیگ آف نیچر کا مرکزی کردار لوسی ہے جو میرے تمام مضامین میں ایک عام کردار بنتا جا رہا ہے۔

3. فن تعمیر

اس سے پہلے کہ ہم شروع کریں، آئیے صرف اپنی چل رہی ایپلیکیشن کا خاکہ بنائیں۔ یہ ایک بہت ہی آسان ایپلی کیشن ہے، لیکن پھر بھی اسے کھینچنا اچھی بات ہے:

اس کی اتنی سادہ وجہ یہ ہے کہ چونکہ JWT ہر درخواست پر چیک کیا جاتا ہے اور ہر درخواست کی عوامی کلید کے خلاف تصدیق ہو جاتی ہے، اس لیے ہم جانتے ہیں کہ جب تک ہم ہر درخواست پر درست ٹوکن بھیجیں گے ہم اسے حاصل کر سکیں گے۔ JWT OAuth2، Okta SSO، یا کسی اور اجازت کے طریقہ کار کے ساتھ مربوط کیا جا سکتا ہے۔ اس صورت میں، ہم جو کچھ کر رہے ہیں وہ تصدیق اور اجازت کو قائم کر رہا ہے۔ ہماری درخواست میں، ہم JWT استعمال کرنے جا رہے ہیں اور اس کے ساتھ، دستخط کے ذریعے اپنے پیغام کی تصدیق کریں۔ اگرچہ ہم درخواست میں لاگ ان نہیں ہوں گے۔ اس کے بجائے، ہم کامیاب تصدیق کے بعد صارفین کو اپنی ایپلیکیشن استعمال کرنے کی اجازت دیں گے۔ اس مقام پر، یہ دیکھنا آسان ہے کہ JWT اس کی اصل میں ایک مکمل ایپلی کیشن کا ایک بہت چھوٹا حصہ ہے۔ بہر حال، کچھ فعالیت کو شامل کرنے کی ضرورت ہے۔ یہ وہ وسائل ہیں جن کی ہمیں ضرورت ہے:

  • توازن کا نظام
  • کریڈٹ سسٹم


آئیے صرف یہ کہتے ہیں کہ ہمارا بنیادی نظام صرف رقم اور کریڈٹ کی درخواستوں کو رجسٹر کرے گا۔ بنیادی طور پر یہ صرف اقدار کو جمع کرے گا۔ آئیے یہ بھی مان لیں کہ کچھ لوگ کریڈٹ حاصل کرنے کے قابل ہوں گے اور دوسروں کو نہیں ملے گا۔ کچھ لوگ پیسے ذخیرہ کر سکیں گے اور دوسرے لوگ کریڈٹ حاصل کر سکیں گے۔

4. ٹیکنالوجیز کا انتخاب

جیسا کہ تعارف میں ذکر کیا گیا ہے، ہم KumuluzEE اپنے انٹرپرائز ایپلیکیشن فریم ورک کے طور پر استعمال کریں گے، اور ہم ایک انتہائی بنیادی ایپلی کیشن کو اس طرح لاگو کریں گے کہ ہم بنیادی JWT اصطلاحات اور تصورات کو دیکھ سکیں۔ درست جاوا ورژن کو یقینی بنائیں۔ اس مرحلے پر، ہمیں کم سے کم Java 17 SDK انسٹال کرنے کی ضرورت ہوگی۔ ہمیں maven، git، ایک جاوا سے مطابقت رکھنے والا IDE جیسے IntelliJ، اور کسی قسم کے شیل کی ضرورت ہوگی۔

5. سیٹ اپ

ہماری درخواست شروع کرنے کے لیے، ہمارے پاس KumuluzEE چند انحصار ہیں۔ یہ بنیادی طور پر ہے کیونکہ KumuluzEE ، بالکل اسی طرح جیسے Spring Boot کو کچھ انحصار کی ضرورت ہے۔ آئیے مختصراً POM فائل پر ایک نظر ڈالتے ہیں:

 <dependencies> <dependency> <groupId>com.kumuluz.ee.openapi</groupId> <artifactId>kumuluzee-openapi-mp</artifactId> </dependency> <dependency> <groupId>com.kumuluz.ee.openapi</groupId> <artifactId>kumuluzee-openapi-mp-ui</artifactId> </dependency> <dependency> <groupId>com.kumuluz.ee</groupId> <artifactId>kumuluzee-microProfile-3.3</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib</artifactId> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.mockk</groupId> <artifactId>mockk-jvm</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.ninja-squad</groupId> <artifactId>springmockk</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.kotest</groupId> <artifactId>kotest-assertions-core-jvm</artifactId> <scope>test</scope> </dependency> </dependencies>

آئیے چند انحصارات پر مختصراً گفتگو کرتے ہیں۔ جیسے ہی آپ اسے پڑھتے ہیں، براہ کرم ہماری pom.xml فائل کو اوپر سے نیچے تک فالو کریں۔ درج ذیل وضاحت کو سمجھنے کے لیے یہ ضروری ہے۔ ہمیں اپنی درخواست کو کام کرنے کے لیے انحصار کے پیکج کی ضرورت ہے۔ خوش قسمتی سے، KumuluzEE ، ہمیں مائیکرو پروفائل لائبریریاں فراہم کرتا ہے جس میں اس ایپلیکیشن کو شروع کرنے کے لیے بنیادی معیاری بنڈل ہوتے ہیں۔ یہ سب KumuluzEE -Microprofile لائبریری میں موجود ہے۔ اپنی ایپ کو تمام JWT پیرامیٹرز کے ساتھ ترتیب دینے کے قابل ہونے کے لیے، ہمیں اس میں ایک مائیکرو پروفائل لائبریری شامل کرنا ہوگی۔ ایک ہی وقت میں، ہمیں JSON پروسیسنگ لائبریری کی ضرورت ہے۔ یہ وہی ہوگا جو جانسن کور کرتا ہے۔ ہمیں یقیناً کام کرنے کے لیے KumuluzEE کے بنیادی حصے کی ضرورت ہے۔ Jetty بنیادی سرور ہے جو KumuluzEE فریم ورک چلاتا ہے۔ یہی وجہ ہے کہ ہمیں اپنے انحصار میں اس کی ضرورت ہے۔ اس بات پر غور کرتے ہوئے کہ ہمیں CDI ضرورت ہے، ہمیں اس کی حمایت کرنے والی لائبریری کی بھی ضرورت ہے۔ اپنے REST اینڈ پوائنٹس کو فعال کرنے کے لیے، ہمیں KumuluzEE کی باقی لائبریری کی ضرورت ہے۔ ہمارا API حاصل کرنے کے لیے، ہمیں پھر ایک Geronimo لائبریری کی ضرورت ہے۔ یہ یقینی بنائے گا کہ ہمارے پاس JSR-374 کا نفاذ دستیاب ہے۔ ہمیں اپنے JWT اور اس کے JSON-formatted مواد کی تشریح کرنے کی بھی ضرورت ہے۔ لومبوک کی واقعی ضرورت نہیں ہے۔ یہ صرف ہر چیز کو خوبصورت اور چمکدار بناتا ہے! لاگ بیک کا ہونا بھی ضروری ہے تاکہ ہم لاگز کی بہتر تشریح کر سکیں اور اپنے نتائج کو سمجھ سکیں۔ آئیے اب اپنے resources فولڈر پر ایک نظر ڈالتے ہیں۔ شروع کرنے کے لیے پہلے یہ سمجھیں کہ ہم اس فولڈر میں کیا تلاش کرنے کی توقع رکھتے ہیں۔ ہمیں اپنی ایپلی کیشن کو JWT ، لاگ بیک سے متعلق کسی چیز سے کنفیگر کرنے کی ضرورت ہے اور آخر میں، ہمیں ان پھلیوں کے بارے میں کچھ کہنے کی ضرورت ہے جو ہم بنانے جا رہے ہیں۔ آئیے سب سے آسان فائل کو دیکھیں۔ beans.xml META-INF میں پایا جا سکتا ہے:

 <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" xmlns:weld="http://jboss.org/schema/weld/beans" bean-discovery-mode="all"> <weld:scan> <weld:exclude name="org.jesperancinha.fintech.model.Accounts"/> </weld:scan> </beans>

یہ صرف ایک عام ہے اور جیسا کہ آپ اب سوچ رہے ہوں گے، ایک پرانی فائل کا تھوڑا سا۔ اس وقت، خیال صرف یہ ہے کہ KumuluzEE چلایا جائے۔ ہمارے پاس ایک خارجی کارروائی ہے۔ یہ ویلڈ سے کہتا ہے کہ بینز ایکشن کے لیے اسکیننگ میں کلاس اکاؤنٹس پر غور نہ کرے۔ یہ ضروری ہے کیونکہ ہم جس عمل کو استعمال کر رہے ہیں، Weld بنیادی طور پر خالی کنسٹرکٹر والی ہر کلاس کو بین سمجھے گا۔ ہم بعد میں دیکھیں گے کہ ہم کیوں نہیں چاہتے کہ اکاؤنٹس کو بین سمجھا جائے۔ اس لمحے کے لیے ذہن میں رکھیں کہ ہم درخواست دائرہ کار کے تحت درخواستیں کر رہے ہیں۔ یہ منطقی ہے کیونکہ ہر درخواست کا ایک مختلف صارف ہو سکتا ہے۔ آئیے اب دیکھتے ہیں کہ " logback " کو کیسے لاگو کیا جاتا ہے۔ یہ META-INF میں بھی پایا جاتا ہے:

 <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT"/> </root> </configuration>

یہ ہمارے logs کے لیے صرف ایک بہت سیدھی سی ترتیب ہے .آخر میں، شاید ہماری درخواست کی سب سے اہم فائل۔ یہ config-template ہے۔ اس مقام پر، یہ نوٹ کرنا ضروری ہے کہ میں نے اس پروجیکٹ میں جو فائلیں بنائی ہیں ان میں سے کچھ ٹیمپلیٹ ڈھانچے کا حصہ ہیں۔ میں بعد میں اس کے بارے میں مزید وضاحت کروں گا۔ اس ٹیمپلیٹ فائل کو ایک config.yml فائل میں تبدیل کیا جانا چاہئے جسے مائیکرو پروفائل پڑھے گا۔ یہ فائل وسائل کی جڑ میں واقع ہے:

 kumuluzee: name: your-financeje-banking version: 1.0.0 jwt-auth: public-key: {{ publicKey }} issuer: {{ issuer }} healthy: true

ہم بعد میں دیکھیں گے کہ ان تمام خصوصیات کا اصل میں کیا مطلب ہے۔ یہ سب خود وضاحتی ہیں۔ PublicKey اور جاری کنندہ تمام پیرامیٹرز ہیں جنہیں تبدیل کر دیا جائے گا۔ ہم اسے بعد میں دریافت کریں گے۔ ہماری باش اسکرپٹ اس بات کو یقینی بنائے گی کہ وہ تبدیل ہوجائیں۔ ہم کوڈنگ کرنے کے لیے تقریباً تیار ہیں، لیکن پہلے، آئیے اپنے JWT ٹوکن ڈھانچے پر ایک نظر ڈالیں۔

6. ہینڈ آن کوڈ

آئیے اپنی بہت چھوٹی ایپلی کیشن بناتے ہیں۔ یہ سیکشن وضاحت کرے گا کہ ہم JWT کے ساتھ کام کرنے کے لیے اپنی درخواست کیسے حاصل کر سکتے ہیں۔ ہم جو دیکھنا چاہتے ہیں وہ یہ ہے کہ آیا ہم صارفین کو اپنے کچھ REST طریقوں تک رسائی کے لیے مخصوص کر سکتے ہیں نہ کہ دوسروں تک۔ اس کوڈ کو دیکھنا شروع کرنے کا ایک طریقہ یہ ہے کہ پہلے اپنے سادہ JWT ٹوکن پر ایک نظر ڈالیں۔ ہمارے منتظم کی مثال یہ ہے:

 { "iss": "joaofilipesabinoesperancinha", "jti": "01MASTERFINANCE", "sub": "admin", "aud": "nature", "upn": "admin", "groups": [ "user", "admin", "client", "credit" ], "user_id": 1, "access": "TOP", "name": "Admin" }

ہمارے JSON میں ان ناموں میں سے ہر ایک کو دعویٰ کہا جاتا ہے۔ ہماری مثال میں، ہم کچھ محفوظ دعوے دیکھتے ہیں:

  • " iss " — یہ ٹوکن جاری کرنے والا ہے۔ ہم من مانی طور پر اس کے لیے ایک قدر کا انتخاب کر سکتے ہیں۔ اس پیرامیٹر کی قدر config.yml میں تبدیل کرنے کے لیے جاری کنندہ متغیر سے مماثل ہونی چاہیے جسے ہم نے پہلے دیکھا ہے۔
  • " jti " — یہ ٹوکن کا ایک منفرد شناخت کنندہ ہے۔ مثال کے طور پر ہم اس دعوے کو استعمال کر سکتے ہیں تاکہ ٹوکن کو دو یا زیادہ بار استعمال ہونے سے روکا جا سکے۔
  • " sub " - یہ ٹوکن کا موضوع ہے۔ یہ صارف یا ہماری پسند کی کوئی بھی چیز ہو سکتی ہے۔ یہ ذہن میں رکھنا ضروری ہے کہ اسے شناخت کنندہ، کلید، نام یا کسی بھی چیز کے طور پر بھی استعمال کیا جا سکتا ہے جسے ہم چاہتے ہیں۔
  • " upn " - صارف کا پرنسپل نام۔ اس کا استعمال صارف کے استعمال کردہ پرنسپل کی شناخت کے لیے کیا جاتا ہے۔
  • " groups " — یہ ان گروپس کی ایک صف ہے جن سے موجودہ صارف کا تعلق ہے۔ بنیادی طور پر یہ طے کرے گا کہ اس ٹوکن کے ساتھ درخواست کیا کر سکتی ہے۔ ہمارے ٹوکن میں، ہم پھر کچھ حسب ضرورت دعوے دیکھتے ہیں۔ ہم اسے صرف محفوظ دعووں کے ساتھ ساتھ استعمال کر سکتے ہیں۔
  • " user_id " — ہم اسے صارف کی شناخت سیٹ کرنے کے لیے استعمال کریں گے۔
  • " access " - ہم صارف کی رسائی کی سطح کا تعین کریں گے۔
  • " name " - صارف کا نام۔

7. ہینڈ آن کوڈ

آئیے ہم اب تک جو کچھ جانتے ہیں اس کا ایک خلاصہ بنائیں۔ ہم جانتے ہیں کہ ہم ٹوکنز کے ساتھ اس ڈھانچے کے ساتھ بات چیت کریں گے جس کا ہم نے تعین کیا ہے۔ مزید، ہم نے اپنی ایپلیکیشن کی کنفیگریشن، لاگ بیک کنفیگریشن ترتیب دی ہے اور آخر میں، ہم نے انٹرپرائز بین کی تلاش کے لیے ایک حسب ضرورت کنفیگریشن ترتیب دی ہے۔ آئیے پیکیج ماڈل کو دیکھیں۔ یہاں ہمیں 3 کلاسیں ملیں گی۔ یہ کلاسیں بنیادی طور پر صرف اکاؤنٹس کے مجموعے اور client اور account کے درمیان نمائندگی کی نمائندگی کرتی ہیں۔ اس طرح ہم kotlin فائل Model.kt کو دیکھ کر شروع کر سکتے ہیں جہاں Client واقع ہے:

 data class Client constructor( @JsonProperty var name: String ?= null )

یہ پہلی ماڈل کلاس ہمارے کلائنٹ کی نمائندگی ہے۔ ہمارے کیس کے لیے ہمارے client صرف ایک نام ہے۔ یہ وہ صارف نام ہے جس کی نمائندگی " jwt " انتساب کے نام سے ہوتی ہے۔ مزید یہ کہ ہمارے پاس Account ہے :

 data class Account( @JsonProperty val accountNumber: String?, @JsonProperty val client: Client? = null, @JsonProperty var currentValue: BigDecimal = BigDecimal.ZERO, @JsonProperty var creditValue: BigDecimal = BigDecimal.ZERO ) { fun addCurrentValue(value: Long) = Account( accountNumber, client, currentValue .add(BigDecimal.valueOf(value)), creditValue ) fun addCreditValue(value: Long): Account = Account( accountNumber, client, currentValue, currentValue .add(BigDecimal.valueOf(value)) ) }


اس کلاس میں، ہم بنیادی طور پر ایک اکاؤنٹ نمبر، ایک کلائنٹ، ایک کرنٹ ویلیو اور آخر میں ایک کریڈٹ ویلیو ترتیب دیتے ہیں۔ نوٹ کریں کہ ہم تمام اقدار کو 0 پر ڈیفالٹ کر رہے ہیں۔ ہم BigDecimal بھی استعمال کر رہے ہیں، خالصتاً اس لیے کہ ہم پیسے کے ساتھ کام کر رہے ہیں۔ پیسہ بالکل درست ہونا چاہیے اور نظام کے چکر یا راؤنڈ ڈاؤن کا شکار نہیں ہو سکتا۔ اس کا مطلب دوسرے الفاظ میں اور مثال کے طور پر یہ ہے کہ ایک نمبر جیسے 0. 0000000000000000000000000000000000000000000000000001 یورو ہر وقت اس نمبر کو رہنا چاہئے۔ اس کے علاوہ، ہم اپنے اکاؤنٹ میں قدریں شامل کرنا چاہتے ہیں۔ یہ وہ جگہ ہے جہاں طریقہ addCurrentValue وجود میں آتا ہے۔ انہی وجوہات کی بنا پر، ہم addCreditValue کے ساتھ اپنا کریڈٹ بھی ٹاپ اپ کریں گے۔ آخر کار، اپنے ڈیٹا سیٹ اپ کے آخری حصے میں ہم کلاس Accounts پر آتے ہیں:

 open class Accounts constructor( open val accountMap: MutableMap<String, Account> = mutableMapOf() )

یہ بنیادی طور پر ہمارے تمام اکاؤنٹس کا صرف ایک مجموعہ ہے۔ ہم اس کے نقشے کے مواد کو ڈیٹا بیس کے رویے کی نقل کرنے کے لیے استعمال کریں گے۔ اب آئیے کنٹرولر پیکج کو دیکھتے ہیں۔ یہ وہ جگہ ہے جہاں ہم اپنے ڈیٹا ماڈل کے ساتھ چلنے والی اپنی ایپلیکیشن بناتے ہیں۔ سب سے پہلے، آئیے کلاس BankApplication پر ایک نظر ڈالتے ہیں:

 @LoginConfig(authMethod = "MP-JWT") @ApplicationPath("/") @DeclareRoles("admin", "creditor", "client", "user") class BankApplication : Application()


اس کے ساتھ ہم 3 اہم باتیں بتا رہے ہیں۔ LoginConfig تشریح کے ساتھ، ہم مائکرو پروفائل کے مطابق JWT ٹوکن کو استعمال کرنے اور سمجھنے کے لیے اس کی وضاحت کرتے ہیں۔ ApplicationPath درخواست کی جڑ کی وضاحت کرتا ہے۔ یہیں سے درخواست کا URL شروع ہوگا۔ ہماری مثال میں، یہ ہوگا HTTP://localhost:8080 ۔ آخر میں، DeclareRoles ان کرداروں کی وضاحت کرتا ہے جو ہماری درخواست کے ذریعے استعمال اور قبول کیے جانے والے ہیں۔ اس صورت حال میں رولز اور گروپس قابل تبادلہ ہیں۔

 annotation class AccountsProduct

فل سکرین موڈ میں داخل ہوں فل سکرین موڈ سے باہر نکلیں۔

اگلا، ہم ایک کیشے آبجیکٹ فیکٹری اکاؤنٹس فیکٹری بناتے ہیں:

 class AccountsFactory : Serializable { @Produces @AccountsProduct @ApplicationScoped fun accounts(): Accounts = Accounts(mutableMapOf()) companion object { @Throws(JsonProcessingException::class) fun createResponse( currentAccount: Account, name: JsonString, accounts: Accounts, log: Logger, objectMapper: ObjectMapper, principal: Principal?, jsonWebToken: JsonWebToken? ): Response { val jsonObject = Json.createObjectBuilder() .add("balance", currentAccount.currentValue) .add("client", name) .build() accounts.accountMap[name.string] = currentAccount log.info("Principal: {}", objectMapper.writeValueAsString(principal)) log.info("JSonWebToken: {}", objectMapper.writeValueAsString(jsonWebToken)) return Response.ok(jsonObject) .build() } } }


یہ فیکٹری یہی وجہ ہے کہ ہم نے خاص طور پر Accounts کی تلاش کو غیر فعال کر دیا۔ تلاش کرنے کے عمل کو بین بنانے کی اجازت دینے کے بجائے، ہم خود کو ایگریگیٹر مثال بناتے ہیں۔ Produces تشریح کا استعمال کرتے ہوئے، ہمیں بین بنانے کی اجازت دیتا ہے۔ اپنی حسب ضرورت تشریح، اکاؤنٹس پروڈکٹ کا استعمال کرتے ہوئے، ہم اس بین کے استعمال کو مزید مخصوص بناتے ہیں۔ آخر میں، ApplicationScoped استعمال کرتے ہوئے، ہم اس کے دائرہ کار کو Application اسکوپ کے طور پر بیان کرتے ہیں۔ دوسرے لفظوں میں، اکاؤنٹ ایگریگیشن بین پوری ایپلی کیشن میں سنگلٹن آبجیکٹ کے طور پر برتاؤ کرے گا۔ JSON جوابات بنانے کے لیے " createResponse " صرف ایک عام طریقہ ہے۔ اب ہمیں جس چیز کی ضرورت ہے وہ دو "وسائل" ہیں۔ یہ بنیادی طور پر بہار میں " Controllers " جیسا ہی ہے۔ یہ ایک مختلف نام ہے، لیکن اس کا بالکل وہی استعمال ہے۔ آئیے AccountsResource کلاس کو دیکھیں:

 @Path("accounts") @RequestScoped @Produces(MediaType.APPLICATION_JSON) open class AccountResource { @Inject @AccountsProduct open var accounts: Accounts? = null @Inject open var principal: Principal? = null @Inject open var jsonWebToken: JsonWebToken? = null @Inject @Claim("access") open var access: JsonString? = null @Claim("iat") @Inject open var iat: JsonNumber? = null @Inject @Claim("name") open var name: JsonString? = null @Inject @Claim("user_id") open var userId: JsonNumber? = null @POST @RolesAllowed("admin", "client", "credit") @Throws(JsonProcessingException::class) open fun createAccount(): Response = createResponse( requireNotNull(accounts).accountMap[requireNotNull(name).string] ?: Account( client = Client(name = requireNotNull(name).string), accountNumber = UUID.randomUUID().toString() ) ) @POST @RolesAllowed("admin", "user") @Path("user") @Throws(JsonProcessingException::class) open fun createUser(): Response { return createResponse( requireNotNull(accounts).accountMap[requireNotNull(name).string] ?: Account( client = Client(name = requireNotNull(name).string), accountNumber = UUID.randomUUID().toString() ) ) } @GET @RolesAllowed("admin", "client") @Throws(JsonProcessingException::class) open fun getAccount(): Response? { return createResponse( requireNotNull(accounts).accountMap[requireNotNull(name).string] ?: return Response.serverError() .build() ) } @PUT @RolesAllowed("admin", "client") @Consumes(MediaType.APPLICATION_JSON) @Throws( JsonProcessingException::class ) open fun cashIn(transactionBody: TransactionBody): Response? { val userAccount = requireNotNull(accounts).accountMap[requireNotNull(name).string] ?: return Response.serverError() .build() val currentAccount = userAccount.addCurrentValue(transactionBody.saldo?: 0) requireNotNull(accounts).accountMap[requireNotNull(name).string] = currentAccount return createResponse(currentAccount) } @GET @Path("all") @Produces(MediaType.APPLICATION_JSON) @Throws( JsonProcessingException::class ) open fun getAll(): Response? { val allAccounts = ArrayList( requireNotNull(accounts).accountMap .values ) logger.info("Principal: {}", objectMapper.writeValueAsString(principal)) logger.info("JSonWebToken: {}", objectMapper.writeValueAsString(jsonWebToken)) return Response.ok(allAccounts) .build() } @GET @Path("summary") @Throws(JsonProcessingException::class) open fun getSummary(): Response? { val totalCredit = requireNotNull(accounts).accountMap .values .map(Account::currentValue) .stream() .reduce { result, u -> result.add(u) } .orElse(BigDecimal.ZERO) val jsonObject = Json.createObjectBuilder() .add("totalCurrent", totalCredit) .add("client", "Mother Nature Dream Team") .build() logger.info("Summary") logger.info("Principal: {}", objectMapper.writeValueAsString(principal)) logger.info("JSonWebToken: {}", objectMapper.writeValueAsString(jsonWebToken)) return Response.ok(jsonObject) .build() } @GET @RolesAllowed("admin", "client") @Path("jwt") open fun getJWT(): Response? { val jsonObject = Json.createObjectBuilder() .add("jwt", requireNotNull(jsonWebToken).rawToken) .add("userId", requireNotNull(userId).doubleValue()) .add("access", requireNotNull(access).string) .add("iat", requireNotNull(iat).doubleValue()) .build() return Response.ok(jsonObject) .build() } @Throws(JsonProcessingException::class) private fun createResponse(currentAccount: Account): Response = AccountsFactory.createResponse( currentAccount, requireNotNull(name), requireNotNull(accounts), logger, objectMapper, principal, jsonWebToken ) companion object { val objectMapper: ObjectMapper = ObjectMapper() val logger: Logger = LoggerFactory.getLogger(AccountResource::class.java) } }

اس کلاس کو مزید تفصیل سے دیکھنے کے لیے ایک لمحہ نکالیں۔ Path تشریح اس بات کی وضاحت کرتی ہے کہ جڑ سے اس وسائل تک کیسے پہنچنا ہے۔ یاد رکھیں کہ ہم "/" کو روٹ کے طور پر استعمال کر رہے ہیں۔ اس صورت میں، "اکاؤنٹس" اس وسائل کے لیے ہمارے روٹ ایکسس پوائنٹ ہیں۔ ہمارے تمام وسائل، ہمارے معاملے میں صرف دو اسکوپ RequestResource کے ساتھ چل رہے ہیں۔ تشریح کے ساتھ Produces اس بات کا تعین کرتا ہے کہ تمام درخواستوں کے تمام جوابات قطع نظر ان کی قسم JSON فارمیٹ شدہ پیغامات کی شکل اختیار کریں گے۔ اپنے aggregator انجیکشن کرنے کے لیے ہم صرف انجیکشن تشریح اور AccountsProduct تشریح کے امتزاج کا استعمال کرتے ہیں:

 @Inject @AccountsProduct open var accounts: Accounts? = null


یہ اس سے میل کھاتا ہے جس کی ہم نے فیکٹری میں تعریف کی ہے۔ مزید یہ کہ ہم سیکیورٹی کے دو اہم عناصر کو بھی انجیکشن کر رہے ہیں۔ ایک principal اور jsonWebToken :

 @Inject open var principal: Principal? = null @Inject open var jsonWebToken: JsonWebToken? = null


JsonWebToken اور Principal دونوں ایک جیسے ہوں گے، اور ہم اسے اپنے لاگز میں دیکھیں گے۔ اپنے وسائل میں، ہم ہمیشہ ایک مخصوص ٹوکن کے ساتھ درخواست سے دعوے لگا سکتے ہیں:

 @Inject @Claim("name") open var name: JsonString? = null @Inject @Claim("user_id") open var userId: JsonNumber? = null


یہ Inject اور Claim تشریحات کے امتزاج سے پورا ہوتا ہے۔ Claim تشریح کے تحت رکھا گیا نام اس بات کی وضاحت کرتا ہے کہ ہم کون سا دعویٰ لگانا چاہتے ہیں۔ ہمیں اس قسم کے ساتھ محتاط رہنا ہوگا جس کے ساتھ ہم اپنے پیرامیٹرز کی وضاحت کرتے ہیں۔ ہماری مثال میں، ہمیں صرف JsonString اور JsonNumber اقسام کی ضرورت ہے۔ سب سے پہلے، آئیے دیکھتے ہیں کہ ہم اکاؤنٹس اور صارفین کیسے بنا رہے ہیں:

 @POST @RolesAllowed("admin", "client", "credit") @Throws(JsonProcessingException::class) open fun createAccount(): Response = createResponse( requireNotNull(accounts).accountMap[requireNotNull(name).string] ?: Account( client = Client(name = requireNotNull(name).string), accountNumber = UUID.randomUUID().toString() ) ) @POST @RolesAllowed("admin", "user") @Path("user") @Throws(JsonProcessingException::class) open fun createUser(): Response { return createResponse( requireNotNull(accounts).accountMap[requireNotNull(name).string] ?: Account( client = Client(name = requireNotNull(name).string), accountNumber = UUID.randomUUID().toString() ) ) }

اکاؤنٹس اور صارفین بنانا


یہاں کا مقصد طریقوں کو الگ کرنے اور انہیں مختلف اجازتیں دینے کے قابل ہونا ہے۔ ہماری مثال میں، وہ دونوں صرف ایک اکاؤنٹ بناتے ہیں، لیکن یہ نوٹ کرنا ضروری ہے کہ صرف کردار والے صارف ہی createUser طریقہ استعمال کر سکتے ہیں۔ اسی طرح، کلائنٹ اور کریڈٹ کے کردار کے حامل صارف ہی طریقہ CreateAccount تک رسائی حاصل کر سکتے ہیں۔ آئیے اب اس وسائل کے PUT درخواست کے طریقہ کار کو تفصیل سے دیکھتے ہیں:

 @PUT @RolesAllowed("admin", "client") @Consumes(MediaType.APPLICATION_JSON) @Throws( JsonProcessingException::class ) open fun cashIn(transactionBody: TransactionBody): Response? { val userAccount = requireNotNull(accounts).accountMap[requireNotNull(name).string] ?: return Response.serverError() .build() val currentAccount = userAccount.addCurrentValue(transactionBody.saldo?: 0) requireNotNull(accounts).accountMap[requireNotNull(name).string] = currentAccount return createResponse(currentAccount) }

کیش ان


ہم جانتے ہیں کہ تشریح PUT اشارہ کرتی ہے کہ یہ طریقہ صرف PUT قسم کی درخواستوں کے ساتھ ہی قابل رسائی ہے۔ تشریح کا راستہ پھر جیٹی کو بتاتا ہے کہ اس طریقہ کا راستہ ایک قدر ہے۔ اسے PathParam نام سے بھی جانا جاتا ہے۔ آخر میں، ہم اس طریقہ کی وضاحت کر سکتے ہیں کہ صرف منتظم یا کلائنٹ کے کردار والے صارفین کو استعمال کرنے کی اجازت ہو۔ ان پٹ ویلیو کو پھر PathParam کے استعمال سے ہمارے لانگ ویلیو متغیر کو منتقل کیا جاتا ہے۔ اگر ہم کسی کردار کی وضاحت نہیں کرتے ہیں، تو صحیح ٹوکن والا کوئی بھی صارف ان طریقوں تک رسائی حاصل کر سکے گا CreditResource طریقہ:

 @Path("credit") @RequestScoped @Produces(MediaType.APPLICATION_JSON) open class CreditResource { @Inject @AccountsProduct open var accounts: Accounts? = null @Inject open var principal: Principal? = null @Inject open var jsonWebToken: JsonWebToken? = null @Inject @Claim("access") open var access: JsonString? = null @Inject @Claim("iat") open var iat: JsonNumber? = null @Inject @Claim("name") open var name: JsonString? = null @Inject @Claim("user_id") open var userId: JsonNumber? = null @GET @RolesAllowed("admin", "credit") @Throws(JsonProcessingException::class) open fun getAccount(): Response = requireNotNull(accounts).let { accounts -> createResponse( accounts.accountMap[requireNotNull(name).string] ?: return Response.serverError().build() ) } @PUT @RolesAllowed("admin", "credit") @Consumes(MediaType.APPLICATION_JSON) @Throws( JsonProcessingException::class ) open fun cashIn(transactionBody: TransactionBody) = requireNotNull(accounts).let { accounts -> requireNotNull(name).let { name -> accounts.accountMap[name.string] = (accounts.accountMap[name.string] ?: return Response.serverError() .build()).addCreditValue(transactionBody.saldo?: 0L) createResponse( (accounts.accountMap[name.string] ?: return Response.serverError() .build()).addCreditValue(transactionBody.saldo?: 0L) ) } } @GET @Path("all") @Produces(MediaType.APPLICATION_JSON) @Throws( JsonProcessingException::class ) open fun getAll(): Response? { val allAccounts = ArrayList( requireNotNull(accounts).accountMap .values ) logger.info("Principal: {}", objectMapper.writeValueAsString(principal)) logger.info("JSonWebToken: {}", objectMapper.writeValueAsString(jsonWebToken)) return Response.ok(allAccounts) .build() } @GET @Path("summary") @Produces(MediaType.APPLICATION_JSON) @Throws( JsonProcessingException::class ) open fun getSummary(): Response? { val totalCredit = requireNotNull(accounts).accountMap .values .map(Account::creditValue) .stream() .reduce { total, v -> total.add(v) } .orElse(BigDecimal.ZERO) val jsonObject = Json.createObjectBuilder() .add("totalCredit", totalCredit) .add("client", "Mother Nature Dream Team") .build() logger.info("Summary") logger.info("Principal: {}", objectMapper.writeValueAsString(principal)) logger.info("JSonWebToken: {}", objectMapper.writeValueAsString(jsonWebToken)) return Response.ok(jsonObject) .build() } @GET @RolesAllowed("admin", "client") @Path("jwt") open fun getJWT(): Response? { val jsonObject = Json.createObjectBuilder() .add("jwt", requireNotNull(jsonWebToken).rawToken) .add("userId", requireNotNull(userId).doubleValue()) .add("access", requireNotNull(access).string) .add("iat", requireNotNull(iat).doubleValue()) .build() return Response.ok(jsonObject) .build() } @Throws(JsonProcessingException::class) private fun createResponse(currentAccount: Account): Response { return AccountsFactory.createResponse( currentAccount, requireNotNull(name), requireNotNull(accounts), logger, objectMapper, principal, jsonWebToken ) } companion object { val objectMapper: ObjectMapper = ObjectMapper() val logger: Logger = LoggerFactory.getLogger(CreditResource::class.java) } }

فرق صرف اتنا ہے کہ admin اور client رولز استعمال کرنے کے بجائے اب ہم admin اور credit رولز استعمال کر رہے ہیں۔ نیز، یہ بھی نوٹ کریں کہ اس resource میں صارفین کے اکاؤنٹس کبھی نہیں بنائے جائیں گے۔ یہ صرف اکاؤنٹ کے resource کے ذریعے ہی ممکن ہے REST

8. درخواست کا استعمال

آئیے استعمال ہونے والی خدمات کی فہرست چیک کریں:


قسم، URL، پے لوڈ، نتیجہ، کرداروں کی اجازت ہے۔
پوسٹ، http://localhost:8080/accounts,n/a,تخلیق شدہ اکاؤنٹ، ایڈمن/کلائنٹ/کریڈٹ
پوسٹ،
http://localhost:8080/accounts/user,n/a,تخلیق شدہ صارف، منتظم/صارف
حاصل کریں،
http://localhost:8080/accounts,n/a,Matching اکاؤنٹ، ایڈمن/کلائنٹ
ڈالو
http://localhost:8080/accounts،{saldo: طویل}، موجودہ بیلنس، منتظم/کلائنٹ
حاصل کریں،
http://localhost:8080/accounts/all,n/a,All کرنٹ اکاؤنٹس، تمام
حاصل کریں،
http://localhost:8080/accounts/summary,n/a,Sum تمام بیلنس کے، تمام
حاصل کریں،
http://localhost:8080/credit,n/a,Matching اکاؤنٹ، ایڈمن/کلائنٹ
ڈالو
http://localhost:8080/credit،{saldo: Long}، موجودہ کریڈٹ، منتظم/کلائنٹ
حاصل کریں،
http://localhost:8080/credit/all,n/a,All کریڈٹ، تمام
حاصل کریں،
http://localhost:8080/credit/summary,n/a,Sum
کریڈٹ، تمام

9. ٹیسٹ ماحول پیدا کرنا

میں نے روٹ فولڈر میں ایک bash فائل بنائی ہے۔ اس فائل کو "setupCertificates.sh" کہا جاتا ہے۔ آئیے اس پر ایک نظر ڈالتے ہیں کہ یہ کیا کرتا ہے:

 #!/bin/bash mkdir -p your-finance-files cd your-finance-files || exit openssl genrsa -out baseKey.pem openssl pkcs8 -topk8 -inform PEM -in baseKey.pem -out privateKey.pem -nocrypt openssl rsa -in baseKey.pem -pubout -outform PEM -out publicKey.pem echo -e '\033[1;32mFirst test\033[0m' java -jar ../your-finance-jwt-generator/target/your-finance-jwt-generator.jar \ -p ../jwt-plain-tokens/jwt-token-admin.json \ -key ../your-finance-files/privateKey.pem >> token.jwt CERT_PUBLIC_KEY=$(cat ../your-finance-files/publicKey.pem) CERT_ISSUER="joaofilipesabinoesperancinha" echo -e "\e[96mGenerated public key: \e[0m $CERT_PUBLIC_KEY" echo -e "\e[96mIssued by: \e[0m $CERT_ISSUER" echo -e "\e[96mYour token is: \e[0m $(cat token.jwt)" cp ../your-financeje-banking/src/main/resources/config-template ../your-financeje-banking/src/main/resources/config_copy.yml CERT_CLEAN0=${CERT_PUBLIC_KEY//"/"/"\/"} CERT_CLEAN1=${CERT_CLEAN0//$'\r\n'/} CERT_CLEAN2=${CERT_CLEAN1//$'\n'/} CERT_CLEAN3=$(echo "$CERT_CLEAN2" | awk '{gsub("-----BEGIN PUBLIC KEY-----",""); print}') CERT_CLEAN4=$(echo "$CERT_CLEAN3" | awk '{gsub("-----END PUBLIC KEY-----",""); print}') CERT_CLEAN=${CERT_CLEAN4//$' '/} echo -e "\e[96mCertificate cleanup: \e[0m ${CERT_CLEAN/$'\n'/}" sed "s/{{ publicKey }}/$CERT_CLEAN/g" ../your-financeje-banking/src/main/resources/config_copy.yml > ../your-financeje-banking/src/main/resources/config_cert.yml sed "s/{{ issuer }}/$CERT_ISSUER/g" ../your-financeje-banking/src/main/resources/config_cert.yml > ../your-financeje-banking/src/main/resources/config.yml rm ../your-financeje-banking/src/main/resources/config_cert.yml rm ../your-financeje-banking/src/main/resources/config_copy.yml echo -e "\e[93mSecurity elements completely generated!\e[0m" echo -e "\e[93mGenerating tokens...\e[0m" TOKEN_FOLDER=jwt-tokens mkdir -p ${TOKEN_FOLDER} # CREATE_ACCOUNT_FILE=createAccount.sh CREATE_USER_FILE=createUser.sh SEND_MONEY_FILE=sendMoney.sh ASK_CREDIT_FILE=askCredit.sh TOKEN_NAME_VALUE=tokenNameValue.csv echo "#!/usr/bin/env bash" > ${CREATE_ACCOUNT_FILE} chmod +x ${CREATE_ACCOUNT_FILE} echo "#!/usr/bin/env bash" > ${CREATE_USER_FILE} chmod +x ${CREATE_USER_FILE} echo "#!/usr/bin/env bash" > ${SEND_MONEY_FILE} chmod +x ${SEND_MONEY_FILE} echo "#!/usr/bin/env bash" > ${ASK_CREDIT_FILE} chmod +x ${ASK_CREDIT_FILE} for item in ../jwt-plain-tokens/jwt-token*.json; do if [[ -f "$item" ]]; then filename=${item##*/} per_token=${filename/jwt-token-/} token_name=${per_token/.json/} cp "${item}" jwt-token.json java -jar ../your-finance-jwt-generator/target/your-finance-jwt-generator.jar \ -p jwt-token.json \ -key ../your-finance-files/privateKey.pem > token.jwt cp token.jwt ${TOKEN_FOLDER}/token-"${token_name}".jwt token=$(cat token.jwt) echo "# Create account: ""${token_name}" >> ${CREATE_ACCOUNT_FILE} echo "echo -e \"\e[93mCreating account \e[96m${token_name}\e[0m\"" >> ${CREATE_ACCOUNT_FILE} echo curl -i -H"'Authorization: Bearer ""${token}""'" http://localhost:8080/accounts -X POST >> ${CREATE_ACCOUNT_FILE} echo "echo -e \"\e[93m\n---\e[0m\"" >> ${CREATE_ACCOUNT_FILE} echo "# Create user: ""${token_name}" >> ${CREATE_USER_FILE} echo "echo -e \"\e[93mCreating user \e[96m${token_name}\e[0m\"" >> ${CREATE_USER_FILE} echo curl -i -H"'Authorization: Bearer ""${token}""'" http://localhost:8080/accounts/user -X POST >> ${CREATE_USER_FILE} echo "echo -e \"\e[93m\n---\e[0m\"" >> ${CREATE_USER_FILE} echo "# Send money to: "${token_name} >> ${SEND_MONEY_FILE} echo "echo -e \"\e[93mSending money to \e[96m${token_name}\e[0m\"" >> ${SEND_MONEY_FILE} echo curl -i -H"'Content-Type: application/json'" -H"'Authorization: Bearer ""${token}""'" http://localhost:8080/accounts -X PUT -d "'{ \"saldo\": "$((1 + RANDOM % 500))"}'" >> ${SEND_MONEY_FILE} echo "echo -e \"\e[93m\n---\e[0m\"" >> ${SEND_MONEY_FILE} echo "# Asking money credit to: "${token_name} >> ${ASK_CREDIT_FILE} echo "echo -e \"\e[93mAsking credit from \e[96m${token_name}\e[0m\"" >> ${ASK_CREDIT_FILE} echo curl -i -H"'Content-Type: application/json'" -H"'Authorization: Bearer ""${token}""'" http://localhost:8080/credit -X PUT -d "'{ \"saldo\": "$((1 + RANDOM % 500))"}'">> ${ASK_CREDIT_FILE} echo "echo -e \"\e[93m\n---\e[0m\"" >> ${ASK_CREDIT_FILE} echo "${token_name},${token}" >> ${TOKEN_NAME_VALUE} fi done

ماحولیات کی نسل

براہ کرم فائل کی پیروی کریں جیسا کہ میں وضاحت کرتا ہوں کہ یہ کیا کرتی ہے۔ یہ ضروری ہے تاکہ ہم سمجھ سکیں کہ یہ کیا کر رہا ہے۔ ہم سب سے پہلے PEM فارمیٹ میں نجی اور عوامی کلید بناتے ہیں۔ اس کے بعد ہم اپنے چلانے کے قابل "your-finance-jwt-generator.jar" کے ساتھ نجی کلید استعمال کرتے ہیں۔ یہ ہمارا چلانے کے قابل جار ہے جو ٹوکنز کی فوری تخلیق کی اجازت دیتا ہے۔ جاری کنندہ کو بعد میں تبدیل نہیں کیا جا سکتا۔ آخر میں، یہ ایک ٹوکن بناتا ہے۔ ہم بعد میں دیکھیں گے کہ اس ٹوکن کو کیسے پڑھا جائے۔ اس ٹوکن میں ہیڈر کے 3 اضافی دعوے ہیں۔ یہ "بچہ"، "ٹائپ" اور "الگ" ہیں۔ یہ مندرجہ ذیل شکل کی پیروی کرتا ہے:

 { "kid": "jwt.key", "typ": "JWT", "alg": "RS256" }

JWT کا ہیڈر

آئیے ان دعوؤں کو مزید قریب سے دیکھتے ہیں:

  • "بچہ" - اشارہ کے دعوی کے طور پر کام کرتا ہے۔ یہ بتاتا ہے کہ ہم کس قسم کا الگورتھم استعمال کر رہے ہیں۔
  • "typ" — یہ IANA میڈیا کی اقسام کا اعلان کرنے کے لیے استعمال ہوتا ہے۔ تین اختیارات ہیں JWT (JSON ویب ٹوکن)، JWE (JSON ویب انکرپشن)، اور JWA (JSON ویب الگورتھم)۔ یہ اقسام ہمارے تجربے سے متعلق نہیں ہیں۔ ہم صرف یہ دیکھیں گے کہ ہمارا ٹوکن واقعی اچھی طرح سے خفیہ نہیں ہے اور اسے ڈکرپٹ کرنا واقعی آسان ہے۔ ہم یہ بھی دیکھیں گے کہ اگرچہ ہم ٹوکنز کو ڈکرپٹ کر سکتے ہیں، لیکن ہم دوسری کارروائیوں کو انجام دینے کے لیے آسانی سے چھیڑ چھاڑ نہیں کر سکتے۔
  • "alg" - اس طرح ہم دستخط کی قسم کی وضاحت کرتے ہیں جسے ہم استعمال کرنا چاہتے ہیں۔ دستخط کو ایک کرپٹوگرافک آپریشن کے طور پر سمجھا جا سکتا ہے جو اس بات کو یقینی بنائے گا کہ اصل ٹوکن تبدیل نہیں کیا گیا ہے اور اس پر بھروسہ کیا گیا ہے۔ ہمارے معاملے میں، ہم RS256 استعمال کر رہے ہیں بصورت دیگر SHA-256 کے ساتھ RSA Signature کے نام سے جانا جاتا ہے۔

اپنی عوامی کلید کے ساتھ، ہم آخر کار اسے اپنے سانچے کو تبدیل کرنے کے لیے استعمال کر سکتے ہیں۔ نئی config.yml فائل کو کچھ اس طرح نظر آنا چاہئے:

 kumuluzee: name: your-financeje-banking version: 1.0.0 jwt-auth: public-key: FAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKE.FAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETO.FAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKEN issuer: joaofilipesabinoesperancinha healthy: true

config.yml


دوسرا مرحلہ چار فائلیں بنانا ہے۔ ڈائرکٹری " jwt-plain-tokens " میں ہر ایک سادہ ٹوکن کے لیے، ہم چار کمانڈز بنائیں گے۔ پہلی کمانڈ یہ ہے کہ ایسے صارفین کو تخلیق کیا جائے جو اپنے اکاؤنٹس کے ساتھ مؤثر طریقے سے کام کر سکیں۔ یہ پروفائلز " admin "، " client " اور " credit " والے صارف ہیں۔ آئیے ان کو بنانے کے لیے " createAccount.sh " فائل چلائیں۔ دوسری کمانڈ باقی صارفین کو بنائے گی جن کے پاس ابھی تک کوئی حقوق نہیں ہیں۔ یہ فائل "createUser.sh" ہے۔ چلو اسے چلاتے ہیں۔ اب ہم دیکھیں گے کہ آخر کار تمام صارفین بن چکے ہیں۔ آئیے اب لین دین کے بارے میں تفصیلات دیکھیں اور باقی دو کمانڈز کو دیکھیں۔ ایک "کیشین" کے لیے اور دوسرا مزید کریڈٹ مانگنے کے لیے۔ پہلی تیار کردہ فائل "sendMoney.sh" bash اسکرپٹ ہے۔ یہاں ہم " cashin " کی تمام درخواستیں تلاش کر سکتے ہیں۔ اس فائل میں آپ کو فی صارف، صارفین کو بے ترتیب رقم کی مقدار بھیجنے کے لیے کرل کی درخواست ملے گی۔ آئیے ایڈمن کیس کو دیکھتے ہیں:

 #!/usr/bin/env bash # Send money to: admin echo -e "\e[93mSending money to \e[96madmin\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer= FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 125}' echo -e "\e[93m\n---\e[0m" # Send money to: cindy echo -e "\e[93mSending money to \e[96mcindy\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 360}' echo -e "\e[93m\n---\e[0m" # Send money to: faustina echo -e "\e[93mSending money to \e[96mfaustina\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 50}' echo -e "\e[93m\n---\e[0m" # Send money to: jack echo -e "\e[93mSending money to \e[96mjack\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 205}' echo -e "\e[93m\n---\e[0m" # Send money to: jitska echo -e "\e[93mSending money to \e[96mjitska\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 332}' echo -e "\e[93m\n---\e[0m" # Send money to: judy echo -e "\e[93mSending money to \e[96mjudy\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 295}' echo -e "\e[93m\n---\e[0m" # Send money to: lucy echo -e "\e[93mSending money to \e[96mlucy\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 160}' echo -e "\e[93m\n---\e[0m" # Send money to: malory echo -e "\e[93mSending money to \e[96mmalory\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 413}' echo -e "\e[93m\n---\e[0m" # Send money to: mara echo -e "\e[93mSending money to \e[96mmara\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 464}' echo -e "\e[93m\n---\e[0m" # Send money to: namita echo -e "\e[93mSending money to \e[96mnamita\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 51}' echo -e "\e[93m\n---\e[0m" # Send money to: pietro echo -e "\e[93mSending money to \e[96mpietro\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 491}' echo -e "\e[93m\n---\e[0m" # Send money to: rachelle echo -e "\e[93mSending money to \e[96mrachelle\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 474}' echo -e "\e[93m\n---\e[0m" # Send money to: sandra echo -e "\e[93mSending money to \e[96msandra\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 417}' echo -e "\e[93m\n---\e[0m" # Send money to: shikka echo -e "\e[93mSending money to \e[96mshikka\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/accounts -X PUT -d '{ "saldo": 64}' echo -e "\e[93m\n---\e[0m"

sendMoney.sh اقتباس

انہی صارفین نے اپنی کریڈٹ کی درخواستیں بھی انہیں تفویض کی ہیں:

 #!/usr/bin/env bash # Asking money credit to: admin echo -e "\e[93mAsking credit from \e[96madmin\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 137}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: cindy echo -e "\e[93mAsking credit from \e[96mcindy\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 117}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: faustina echo -e "\e[93mAsking credit from \e[96mfaustina\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 217}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: jack echo -e "\e[93mAsking credit from \e[96mjack\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 291}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: jitska echo -e "\e[93mAsking credit from \e[96mjitska\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 184}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: judy echo -e "\e[93mAsking credit from \e[96mjudy\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 388}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: lucy echo -e "\e[93mAsking credit from \e[96mlucy\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 219}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: malory echo -e "\e[93mAsking credit from \e[96mmalory\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 66}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: mara echo -e "\e[93mAsking credit from \e[96mmara\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 441}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: namita echo -e "\e[93mAsking credit from \e[96mnamita\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 358}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: pietro echo -e "\e[93mAsking credit from \e[96mpietro\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 432}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: rachelle echo -e "\e[93mAsking credit from \e[96mrachelle\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 485}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: sandra echo -e "\e[93mAsking credit from \e[96msandra\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 500}' echo -e "\e[93m\n---\e[0m" # Asking money credit to: shikka echo -e "\e[93mAsking credit from \e[96mshikka\e[0m" curl -i -H'Content-Type: application/json' -H'Authorization: Bearer FAKE.FAKE.FAKE' http://localhost:8080/credit -X PUT -d '{ "saldo": 89}' echo -e "\e[93m\n---\e[0m"

askCredit.sh اقتباس



ہمارے تمام characters لیگ آف Nature کا حصہ ہیں۔ اس بینکنگ سسٹم کا حصہ بننے کے لیے بنیادی طور پر صرف کچھ لوگوں کا گروپ۔ اس تناظر میں وہ ماحولیات کا دفاع کر رہے ہیں۔ یہ مضمون کے لیے واقعی متعلقہ نہیں ہے کہ لوگوں کا یہ گروپ کیا کرتا ہے یا کہانی میں وہ کہاں فٹ ہوتے ہیں، لیکن سیاق و سباق کے لیے، وہ ماحول کے دفاع اور موسمیاتی تبدیلی کے اثرات کو کم کرنے کے لیے کارروائیوں میں حصہ لیتے ہیں۔ ہمارے کچھ characters سب کچھ کر سکتے ہیں، دوسرے کچھ نہیں کر سکتے اور دوسرے صرف "کیشین" یا صرف "کریڈٹ مانگ" سکتے ہیں۔ یہ بھی نوٹ کریں کہ میں حساس معلومات کو مبہم کر رہا ہوں۔ ان ٹوکنز کو عام طور پر کسی خاص URL پر شیئر نہیں کیا جانا چاہیے اور نہ ہی دکھائی دینا چاہیے۔ وہ ہاں ہمیشہ براؤزر ڈویلپر کنسول کے ذریعے دستیاب ہوتے ہیں لیکن بہرحال کچھ درخواستوں کی protect کرنا ہے۔ یہ ایک تصور ہے جسے "سیکیورٹی-فی-مبہمیت" کے نام سے جانا جاتا ہے and اگرچہ یہ تکنیکی طور پر صارف کو ٹوکن کے استعمال کے بارے میں آگاہ ہونے سے نہیں روکتا، لیکن یہ ایک رکاوٹ کا کام کرتا ہے۔ دونوں طریقوں میں، جب ہم رقم جمع کرتے ہیں یا جب ہم کریڈٹ کے لیے پوچھیں، نوٹس کریں کہ ہر درخواست کے لیے، ہم 1 سے 500 کے درمیان ایک بے ترتیب نمبر بھیج رہے ہیں۔ اب ہم اپنی درخواست شروع کرنے کے لیے تقریباً تیار ہیں، لیکن پہلے، آئیے تھوڑا سا غوطہ لگائیں۔ مزید نظریہ.

10. JWT ٹوکن کیسے بنایا جاتا ہے۔




اب جب کہ ہم نے اپنے ٹوکن بنائے ہیں، آئیے ان میں سے ایک کو دیکھتے ہیں۔ میں آپ کو ایک مبہم ٹوکن دکھانے جا رہا ہوں، اور ہم اسے سمجھنے کے لیے استعمال کرنے جا رہے ہیں۔ ہمارا ٹوکن یہ ہے: FAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKE ۔ FAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETO . FAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKENFAKETOKEN یہاں جو بات نوٹ کرنا ضروری ہے وہ یہ ہے کہ ہمارے ٹوکن کو تین حصوں میں تقسیم کیا گیا ہے:

  • ہیڈر — یہ ایک بیس 64 انکوڈ شدہ JSON کنفیگریشن ہیڈر ہے، جیسا کہ ہم نے اوپر بات کی ہے۔
  • پے لوڈ — یہ ایک بیس 64 انکوڈ شدہ JSON پے لوڈ ہے۔ یہیں پر ہم نے اپنے محفوظ اور حسب ضرورت دعووں کی وضاحت کی ہے۔ ہم یہاں پرائیویٹ اور پبلک کلیمز کی بھی تعریف کر سکتے ہیں۔ یہ دونوں اپنی مرضی کے دعووں کے تحت آتے ہیں۔ ایک فوری نوٹ کے طور پر، ہم ان دونوں دعووں کے ساتھ جو چاہیں کر سکتے ہیں۔ تاہم عوامی دعووں کو IANA JSON ویب ٹوکن رجسٹری میں بیان کردہ دعووں کے طور پر کہا جاتا ہے۔ یہ ضروری ہے کہ ہم رجسٹری کے ساتھ ٹکراؤ سے بچنے کے لیے اپنے ٹوکن کو ایک خاص طریقے سے نام دیں۔ عوامی دعووں کو معیاری اختیاری کے طور پر بھی بیان کیا جا سکتا ہے۔ نجی دعوے کسی معیار کی پیروی نہیں کرتے اور ان کی وضاحت کرنا ہم پر منحصر ہے۔
  • دستخط - یہ وہ جگہ ہے جہاں ہم تھوڑا تخلیقی ہو سکتے ہیں۔ دستخط Header اور Payload کا ایک cyphered مجموعہ ہے. ہم اس الگورتھم کا فیصلہ کرتے ہیں جسے ہم استعمال کرنا چاہتے ہیں اور یہ ٹوکن بنیادی طور پر اس بات کا تعین کرے گا کہ آیا ہم جو پیغام بھیج رہے ہیں اس پر بھروسہ کیا جائے گا۔ یہ اس امتزاج کے لیے منفرد ہے اور ہمارا سرور اس "عوامی کلید" کا استعمال کرے گا جسے ہم نے یہ تعین کرنے کے لیے بنایا ہے کہ آیا ہمارے پاس کوئی مماثلت ہے۔ اگر آپ کو اوپر سے یاد ہے تو ہم اپنی مثال میں RS256 استعمال کر رہے ہیں۔


اس سے پہلے کہ ہم جاری رکھیں، براہ کرم نوٹ کریں کہ ہماری مثال میں Header اور Payload دونوں کو decyphered جا سکتا ہے۔ ہم صرف پے لوڈ یا ہیڈر کے ساتھ چھیڑ چھاڑ نہیں کر سکتے اور پھر بھی اسے قابل بھروسہ بناتے ہیں۔ نقصان دہ ٹوکن کے ممکنہ اثرات سے تحفظ صرف ہمارے منتخب کردہ الگورتھم کے ذریعے ہی محفوظ کیا جا سکتا ہے۔ اس لیے دانشمندی سے انتخاب کریں۔ اگر آپ کسی ایسی تنظیم میں کام کر رہے ہیں جہاں سرفہرست خفیہ معلومات ایک تشویش کا باعث ہیں، جیسے کہ بینک، تو براہ کرم وہ نہ کریں جو ہم کرنے والے ہیں۔ یہ ہمارے لیے مقامی طور پر بنائے گئے ٹوکنز کے مواد کو آن لائن چیک کرنے کا ایک طریقہ ہے۔ سب سے پہلے، آئیے https://jwt.io/ پر جائیں اور اپنے JWT ٹوکن کو پُر کریں۔ وہ ٹوکن استعمال کریں جو آپ نے ابھی تیار کیا ہے:


ہمارے ٹوکن کے مواد کو چیک کرنے کے لیے https://jwt.io/ کا استعمال کرتے ہوئے آئیے اس بات کا جائزہ لیں کہ ہمارے پاس یہاں کیا ہے۔ یہ ہمارا ایڈمنسٹریٹر ٹوکن ہے۔ وہ شخص ہماری مثال میں "ایڈمن" ہے۔ ہم دیکھ سکتے ہیں کہ ہمارے پیرامیٹرز تمام دستیاب ہیں۔ ہماری فہرست میں ہم "sub"، "aud"، "upn"، "access"، "user_id"، "iss"، "name"، "groups" اور آخر میں "jti" دیکھتے ہیں۔ ہمارے پاس کچھ اضافی دعوے بھی ہیں۔ آئیے ان کو دیکھتے ہیں:



" auth_time " - یہ تب ہوتا ہے جب توثیق ہوتی ہے۔ ہمارا ٹوکن جیسا کہ اتوار، 17 جولائی 2022 16:15:47 GMT+02:00 DST " iat " کو تصدیق شدہ ہے — یہ تب ہوتا ہے جب ٹوکن بن جاتا ہے۔ ہمارے معاملے میں، یہ auth_time کے ساتھ ساتھ ہوتا ہے۔" exp " — یہ ٹوکن کی میعاد ختم ہونے کی تاریخ ہے۔ اس کی میعاد اتوار، 17 جولائی 2022 16:32:27 GMT+02:00 DST کو ختم ہوگی۔ ہم نے اپنے ٹوکن میں کوئی میعاد ختم ہونے کی تاریخ نہیں بتائی۔ اس کا مطلب ہے کہ JWT اپنی ڈیفالٹ ویلیو ~15 منٹ استعمال کرتا ہے۔

آئیے اب کچھ ٹیسٹ کرتے ہیں۔

11. ایپلیکیشن چلانا

کوڈ GitHub پر استعمال کرنے کے لیے تیار ہے۔ اگر ہم کوڈ چیک کرتے ہیں اور اسے Intellij کے ساتھ کھولتے ہیں تو ہمیں اس بات سے آگاہ ہونا چاہیے کہ ہم اس ایپلی کیشن کو اسپرنگ بوٹ ایپلی کیشن کی طرح نہیں چلا سکتے۔ اسے چلانے کے لیے کوئی "psvm" نہیں ہے۔ اس کے بجائے، ہم صرف تیار کردہ جار کو براہ راست چلا سکتے ہیں اور اس بات کو یقینی بنا سکتے ہیں کہ ہم اس سے پہلے ایک "mvn build" بنائیں۔ یہ ہے کہ میں اس وقت اسے کس طرح استعمال کر رہا ہوں:

[ ] https://github.com/jesperancinha/your-finance-je "ایپلیکیشن چلانے کے لیے ماحولیات کا سیٹ اپ")



آئیے اب " setupCertificates.sh " اسکرپٹ کو دوبارہ چلائیں۔ مجھے نہیں معلوم کہ آپ کو یہاں پہنچنے میں کتنا وقت لگا لیکن اس بات کا بہت امکان ہے کہ اس وقت 15 منٹ پہلے ہی گزر چکے ہوں۔ صرف اس صورت میں، بس انہیں دوبارہ چلائیں۔ آئیے اپنی ایپ شروع کریں! ہم اسے اس طرح شروع کر سکتے ہیں:

 mvn clean install java -jar your-financeje-banking/target/your-financeje-banking.jar

یا ہم اسے اپنی تیار چلنے والی ترتیب کے ذریعے چلا سکتے ہیں۔ اگر آپ ہر چیز کو سمجھنا چاہتے ہیں تو پہلے سے ریپو اور میک فائل کو چیک کریں:

 make dcup-full-action

یہ اسکرپٹ 2 سروسز چلائے گی۔ ایک پورٹ 8080 پر اور دوسرا پورٹ 8081 پر۔ پورٹ 8080 پر ہم اس سافٹ ویئر کا ایک ورژن چلائیں گے جو JWT ٹوکن تیار کرنے کے لیے اپنا کوڈ چلاتا ہے۔ پورٹ 8081 پر، ہم Adam Bien کے بنائے ہوئے jwtknizr جنریٹر کا استعمال کرتے ہوئے ایک ورژن چلائیں گے۔ ہم اس مضمون پر توجہ مرکوز کریں گے، تاہم پورٹ 8080 پر چلنے والی سروس پر۔ اگر آپ چاہیں تو آپ cypress اس کے ساتھ بھی چلا سکتے ہیں:

 make cypress-open

اس سے cypress کنسول open گا، اور آپ اپنی پسند کے براؤزر کے ساتھ ٹیسٹ چلانے کے قابل ہو جائیں گے۔ تاہم، اس مرحلے پر براؤزر کے اختیارات ابھی تک محدود ہیں۔ زیادہ تر درخواستیں دراصل cypress کی طرف سے فراہم کردہ کمانڈ لائن درخواستیں ہوں گی cypress براہ کرم اپنے براؤزر پر جائیں اور اس مقام پر جائیں:

http://localhost:8080/accounts/all

ہمیں اس طرح کا نتیجہ ملنا چاہئے:


جیسا کہ ہم دیکھ سکتے ہیں، " Malory "، " Jack Fallout "، اور " Jitska " کے پاس کوئی کریڈٹ یا پیسہ نہیں ہے۔ اس کی وجہ یہ ہے کہ انہیں صرف یوزر گروپ دیا گیا ہے۔ یہ بھی نوٹ کریں کہ Shikka کوئی کریڈٹ نہیں دیا گیا ہے۔ " Shikka "، ہمارا واحد کلائنٹ ہے جس کے پاس گروپ کریڈٹ نہیں ہے۔ اگر ہم لاگز کو دیکھیں تو ہم دیکھ سکتے ہیں کہ کامیاب آپریشنز اس فارمیٹ میں ہوتے ہیں:

 Sending money to admin HTTP/1.1 200 OK Date: Sun, 17 Jul 2022 15:01:13 GMT X-Powered-By: KumuluzEE/4.1.0 Content-Type: application/json Content-Length: 32 Server: Jetty(10.0.9) {"balance":212,"client":"Admin"}


A 200 ہمیں بتاتا ہے کہ آپریشن کامیابی سے ہوا ہے۔ "مالوری"، "جیک فال آؤٹ" اور "جٹسکا" کی صورت میں، دونوں آپریشن ناکام ہو جاتے ہیں اور پھر ہمیں اس قسم کا پیغام ملے گا:

 Sending money to jitska HTTP/1.1 403 Forbidden X-Powered-By: KumuluzEE/4.1.0 Content-Length: 0 Server: Jetty(10.0.9)

A 403 ہمیں بتاتا ہے کہ ہمارے JWT ٹوکن کی توثیق ہو چکی ہے اور یہ قابل اعتماد ہے۔ تاہم، صارف کو یہ آپریشن کرنے سے منع کیا گیا ہے۔ دوسرے لفظوں میں، انہیں مقررہ طریقہ تک رسائی حاصل نہیں ہے۔

آئیے اپنے ٹوکنز کے ساتھ تھوڑا سا چھیڑ چھاڑ کریں۔ اگر ہم sendMoney.sh فائل کے کچھ ٹوکن تبدیل کرتے ہیں۔ ہمیں یہ حاصل کرنا چاہئے:

 Sending money to admin HTTP/1.1 401 Unauthorized X-Powered-By: KumuluzEE/4.1.0 WWW-Authenticate: Bearer realm="MP-JWT" Content-Length: 0 Server: Jetty(10.0.9)

فل سکرین موڈ میں داخل ہوں فل سکرین موڈ سے باہر نکلیں۔

اس 401 کا مطلب ہے کہ ہمارے ٹوکن کی توثیق نہیں ہوئی تھی۔ اس کا مطلب ہے کہ وہ عوامی کلید جسے سرور یہ چیک کرنے کے لیے استعمال کرتا ہے کہ آیا ہمارے ٹوکن پر بھروسہ کیا جانا ہے، کوئی مماثلت نہیں ملی۔ اگر عوامی کلید JWT ٹوکن کے دستخط کی جانچ اور توثیق نہیں کر سکتی، تو یہ اسے مسترد کر دے گی۔

ریکیپ کے طور پر، ہیڈر اور "پے لوڈ" کو خفیہ نہیں کیا گیا ہے۔ وہ صرف بیس 64 "انکوڈڈ" ہیں۔ اس کا مطلب یہ ہے کہ "ڈی کوڈنگ" ہمیں ہمیشہ اس کے اندر جھانکنے کی اجازت دیتی ہے کہ پے لوڈ اصل میں کیا ہے۔ اگر ہم اپنے پے لوڈ کو چھپنے سے بچانے کے لیے تلاش کر رہے ہیں، تو ہمیں کسی اور چیز کے لیے ٹوکن کا "پے لوڈ" استعمال نہیں کرنا چاہیے بلکہ شناختی پیرامیٹرز کو منتخب کرنا چاہیے۔ مسئلہ درحقیقت اس وقت ہوتا ہے جب کوئی JWT ٹوکن پر ہاتھ ڈالتا ہے، مثال کے طور پر، جب TLS ٹنل سے سمجھوتہ کیا گیا ہو اور کوئی شخص تبادلہ شدہ پیغامات کے مواد کو پڑھنے کے قابل ہو۔ جب ایسا ہوتا ہے، تب بھی ایک اور تحفظ باقی رہتا ہے۔ اور یہ دستخط ہے۔ صرف ایک ہی جو پیغام میں جانے کی توثیق کر سکتا ہے وہ سرور ہے جس میں عوامی کلید موجود ہے۔ یہ عوامی کلید، اگرچہ عوامی ہے، صرف دستخط اور "ہیڈر + پے لوڈ" کے خلاف چل کر آنے والے پیغام کو درست کرنے کی اجازت دیتی ہے۔

12. نتیجہ

ہم اپنے سیشن کے اختتام پر پہنچ چکے ہیں۔ اس پر عمل کرنے کے لیے آپ کا شکریہ۔ ہم دیکھ سکتے ہیں کہ JWT ٹوکن کس طرح کمپیکٹ ہیں اور ان کے XML ہم منصب، SAML ٹوکنز کے مقابلے میں بہت کم لفظی ہیں۔ ہم نے دیکھا ہے کہ مخصوص طریقوں کے لیے درکار اجازتیں حاصل کرنے کے لیے ٹوکن بنانا اور استعمال کرنا کتنا آسان ہے اور ہم دستخط شدہ ٹوکن کے ذریعے وہاں کیسے پہنچتے ہیں۔ مجھے JWT کیسے کام کرتا ہے اس کا اندازہ حاصل کرنا بہت ضروری ہے۔ امید ہے کہ، اس کے ساتھ، میں نے آپ کو JWT ٹوکنز کے کام کرنے کے بارے میں ایک اچھا تعارف دیا ہے۔ یہ سب کیسے کام کرتا ہے، اس کے بارے میں بہتر اندازہ حاصل کرنے کے لیے، میں آپ کو مشورہ دیتا ہوں کہ لاگو cypress ٹیسٹوں کے ساتھ کھیلیں۔ یہ دیکھنے کا ایک بہترین طریقہ ہے کہ درخواستیں کیسے کی جا رہی ہیں اور ہم کس چیز کی جانچ کر رہے ہیں اور کیا توقع کی جا رہی ہے۔ اس کے بعد آپ کو یہ بھی بہتر اندازہ ہو جائے گا کہ کیوں کچھ صارفین کو کچھ آپریشنز کرنے پڑتے ہیں اور دوسرے کیوں نہیں کرتے۔ میں نے اس ایپلی کیشن کے تمام سورس کوڈ کو GitHub پر رکھ دیا ہے، مجھے امید ہے کہ آپ نے اس مضمون کو اتنا ہی لطف اندوز کیا ہو گا جتنا مجھے لکھنے میں آیا۔ پڑھنے کے لیے آپ کا شکریہ!

13. حوالہ جات