Android one time password (OTP) user registration/

2019-01-22 16:37发布

问题:

I want to implement OTP functionality in my android application. In this application, after signup user will receive one time password key. After verifying OTP, user will be able to register/open account successfully by using that OTP. What i need to do achieve this?

回答1:

Check google authenticator. https://code.google.com/p/google-authenticator/ it is open source project with OTP functionality

Source code for android app https://code.google.com/p/google-authenticator/source/browse/?repo=android

Here is source code for server side https://github.com/chregu/GoogleAuthenticator.php

Wikipedia article http://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm



回答2:

I have implement a very simple method of OTP..

  1. Activity generates a random 5 digit number and send it to mobile number through SMS gateway.
  2. On recieving sms, SMS body read by Broadcast Reciever and copy the code from SMS body to OTP EditText.
  3. If random code generated by activity and code sent via sms are same then user should get further access.


回答3:

As @Vipin mentioned, the best way would be implementing it your self:

First, you have to generate a 4-digit(or whatever you want) pin code, for example:

int range = 9;  // to generate a single number with this range, by default its 0..9
int length = 4; // by default length is 4

public int generateRandomNumber() {
    int randomNumber;

    SecureRandom secureRandom = new SecureRandom();
    String s = "";
    for (int i = 0; i < length; i++) {
        int number = secureRandom.nextInt(range);
        if (number == 0 && i == 0) { // to prevent the Zero to be the first number as then it will reduce the length of generated pin to three or even more if the second or third number came as zeros
            i = -1;
            continue;
        }
        s = s + number;
    }

    randomNumber = Integer.parseInt(s);

    return randomNumber;
}

Then, you have to save this number somewhere save, for example in your preferences:

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("OTP_PIN", randomNumber);
editor.commit();

The next step, would be using a proper SMS gateway to send that OTP to the corresponding phone number, for me I'm using clickATell with our php server to send the message, the api documentation is pretty clear. And if you want to send the message directly from the application, may be SMSgateway can help.

The final step, is to verify the code received by SMS is the one stored in device preferences, this is pretty easy and straight forward, all you have to do is to provide an EditText for the user allowing him to enter the code received by his phone, if the code matches the OTP saved in device preferences, make him go through the app, otherwise, display a proper error message.


a classy move: Not mandatory but preferably, as a lot of applications doing you can provide SMS listener to listen to the upcoming messages, getting the code from the received message, display it in the code verification editText, verify it, if true, go through the app.

in manifest.xml:

<receiver
    android:name=".Services.SmsListener"
    android:exported="true"
    android:permission="android.permission.BROADCAST_SMS">
    <intent-filter android:priority="999">
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

the listener:

public class SmsListener extends BroadcastReceiver {

    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("messageBody", intent.getAction());
        if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
            try {
                String messageBody = "";
                for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
                    messageBody = smsMessage.getMessageBody();
                }
                Intent messageReceived = new Intent(SVPreferences.SMS_RECEIVED);
                messageReceived.putExtra("sms", messageBody);
                context.sendBroadcast(messageReceived); // when receiving it somewhere in your app, subString the additional text and leave only the code, then place it in the editText and do your verification
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

the receiver:

BroadcastReceiver receiveSMS = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            String smsBody = intent.getStringExtra("sms");
            String pin = smsBody.replace(getResources().getString(R.string.your_extra_text), "").trim();
            editText_confirm_pin.setText(pin);
            if (validatePin(pin))
                // go through the app
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
};