سرویس احراز هویت پیامکی


سلیب که از امنیت کوئرا به ستوه آمده بود، با نیما (اسطوره‌ی امنیت در سطح بین‌المللی) در این‌باره صحبتی را شروع کرد. نیما به این نتیجه رسید که کوئرا نیاز به یک اقدام امنیتی در ورود به حساب کاربری دارد. پیشنهاد او تأیید از طریق SMS بود و تأکید اکیدی بر زمان انقضای آن‌ها داشت. به نظر او هر کد تأیید باید فقط برای ۱۰ ثانیه معتبر می‌بودند و پس از گذشت بیش از ۱۰ ثانیه، کد دیگر مورد قبول نباشد. سلیب از آن‌سو تاکید بر ماندگاری دیتا‌ها داشت. به نظر او نیاز بود تا تمامی اطلاعات را به فرمت زیر در یک فایل CSV نگه‌داری کند:

extensionFromNamesample-data.csv
Phone,Code,Expiration
CSV

در ستون اول شماره مورد نظر، ستون دوم کد ساخته شده برای شماره و در ستون سوم اعتبار کد را نمایش می‌دهد، در ادامه به بیان جزئیات بیشتر سؤال می‌پردازیم.

جزئیات پروژه🔗

پروژه‌ی اولیه را از این لینک دانلود کنید.

ساختار فایل‌های پروژه به‌صورت زیر است:

SMSAuthentication
├── pom.xml
├── src
│   ├── main
│   │   └── java
│   │       └── org
│   │           └── quera
│   │               └── smsauthentication
│   │                   └── SMSAuthentication.java
│   └── test
│       └── java
│           └── org
│               └── quera
│                   └── smsauthentication
│                       └── SMSAuthenticationSampleTest.java
└── test.csv
Plain text

شما باید متدهای generateCode، sendAuthenticationSMS، loadData، verifyCode موجود در کلاس SMSAuthentication را مطابق با خواسته‌های سؤال پیاده‌سازی کنید. نمای کلی فایل مورد نظر به شکل زیر است:

extensionFromNameSMSAuthentication.java
package org.quera.smsauthentication;

import ...

public class SMSAuthentication {
    public static String generateCode() {
        // TODO: Implement
    }

    public static String sendAuthenticationSMS(String phone, String path) {
        // TODO: Implement
    }

    public static List<String[]> loadData(String path) {
        // TODO: Implement
    }

    public static boolean verifyCode(String code, String phone, String path) {
        // TODO: Implement
    }

    public static void main(String[] args) {
        System.out.println(sendAuthenticationSMS("09381358888", "test.csv"));
        Scanner sc = new Scanner(System.in);
        String code = sc.next();
        System.out.println(verifyCode(code,"09381358888","test.csv"));
    }
}
Java

متد generateCode🔗

این متد باید یک رشته تصادفی به طول ۵ بسازد و مقدار آن را برگرداند. در این رشته می‌توانید از فقط متشکل از ارقام انگلیسی استفاده کنید. نمونه‌ی اجرای متد در زیر آمده است:

extensionFromNameTerminal
>>> generateCode()
40142
>>> generateCode()
18272
>>> generateCode()
00168
Java

متد sendAuthenticationSMS🔗

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

  • کلید phone برابر با مقدار شماره مورد نظر خواهد بود.
  • کلید code برابر با کد ساخته شده برای شماره مورد نظر خواهد بود.
  • کلید exp برابر با زمانی که کد مورد نظر منقضی می‌شود است، زمان در این سؤال به فرمت "yyyy/MM/dd-HH:mm:ss" استفاده می‌شود.

این متد باید این محتوا را درون فایل CSV موجود در آدرس path ذخیره کند. خروجی و رفتار خواسته شده در بخش مثال با جزئیات بیشتری نمایش داده شده است.

مثال🔗

extensionFromNameTerminal
>>> sendAuthenticationSMS("09381354444", "test.csv")
{"phone":"09381354444","code":"06505","exp":"2022/10/04-18:02:15"}
>>> sendAuthenticationSMS("09381354443", "test.csv")
{"phone":"09381354443","code":"26052","exp":"2022/10/04-18:07:39"}
>>> sendAuthenticationSMS("09381354444", "test.csv") // duplicate
{"phone":"09381354444","code":"00300","exp":"2022/10/04-19:02:48"}
Java

محتوای چند خط آخر فایل test.csv پس از اجرای بالا برابر با زیر خواهد بود:

extensionFromNametest.csv
Phone,Code,Expiration
...
09381354444,06505,2022/10/04-18:02:15
09381354443,26052,2022/10/04-18:07:39
09381354444,00300,2022/10/04-19:02:48
CSV

متد loadData🔗

این متد یک رشته به عنوان آدرس فایلی که باید اطلاعات آن را بخواند، به عنوان ورودی دریافت می‌کند. خروجی این متد لیستی از آرایه‌ای از Stringها خواهد بود که برابر با مقادیر موجود در فایل CSV ورودی متد است.

مثال🔗

برای مثال فرض کنید محتوای فایل CSV به‌صورت زیر باشد:

extensionFromNametest.csv
Phone,Code,Expiration
09381354444,06505,2022/10/04-18:02:15
09381354443,26052,2022/10/04-18:07:39
09381354444,00300,2022/10/04-19:02:48
CSV

اگر متد را به‌صورت زیر فراخوانی کنیم

extensionFromNamesnippet
List<String[]> allData = loadData("test.csv");
Java

و بخواهیم خروجی متد را به‌صورت زیر چاپ کنیم:

extensionFromNamesnippet
for(String[] data : allData) {
    for(String attr : data) {
        System.out.print(attr + " ");
    }
    System.out.println();
}
Java

خروجی به‌صورت زیر خواهد بود

09381354444 06505 2022/10/04-18:02:15
09381354443 26052 2022/10/04-18:07:39
09381354444 00300 2022/10/04-19:02:48
Plain text

دقت کنید که خط اول (یا همان Phone,Code,Expiration) در خروجی متد وجود ندارد.

متد verifyCode🔗

این متد یک رشته به عنوان کد، یک رشته به عنوان شماره و رشته‌ای دیگر به عنوان آدرس فایلی که باید اطلاعات را از آن بخواند، به عنوان ورودی دریافت می‌کند. خروجی این متد یک boolean است که در صورتی که کد با شماره مورد نظر تطابق داشت و کد منقضی نشده بود، باید مقدار true برگرداند و در غیر این صورت مقدار false برگرداند.

نکات🔗

  • شما در این سؤال مجاز به تغییر فایل pom.xml نیستید.
  • برای کار با JSON، تنها مجاز به استفاده از کتابخانه opencsv هستید.
  • برای کار با CSV ، تنها مجاز به استفاده از کتابخانه jackson-databind هستید.
  • به جز کتابخانه‌های موجود در pom.xml، تنها مجاز به استفاده از کتابخانه‌های استاندارد جاوا هستید.
  • هر کد تنها ده ثانیه زمان دارد.
  • دقت کنید که تاریخ و زمان انقضای کد را باید دقیقا برابر با ۱۰ ثانیه پس از تولید کد (یا فراخوانی متد sendAuthenticationSMS) قرار دهید.
  • شما مجاز به عوض کردن فرمت ذخیره‌سازی اطلاعات در فایل CSV نیستید و باید دقیقا برابر با فرمت خواسته شده، اطلاعات را ذخیره سازی کنید.
  • داوری این سؤال، بیشتر از باقی مسائل طول می‌کشد.

آن‌چه باید آپلود کنید🔗

پس از پیاده‌سازی موارد خواسته‌شده، فایل تمامی پروژه را زیپ کنید و آن را آپلود کنید. فایل زیپ شما باید به‌صورتی باشد که پس از خروج از حالت فشرده، پوشه‌ی src مشاهده شود.