2013-01-17 243 views
6

我需要一種方法來驗證我的Android應用程序中設置的手機號碼是否正確,如「所有權」 - 而不是手機號碼的數據驗證。Android電話號碼驗證

E.g. WhatsApp的做法...

我知道如何通過使用代碼和東西進行短信驗證。事情是這是一個免費的Android應用程序,我不想在應用程序免費時支付每個發送的短信。壞的商業模式...

有沒有辦法做到這一點安全和自由?

使用API​​代碼似乎不太安全,所以它不是一個選項,我怕:

TelephonyManager tMgr (TelephonyManager)mAppContext.getSystemService(Context.TELEPHONY_SERVICE); 
mPhoneNumber = tMgr.getLine1Number(); 
+0

你是什麼意思,它的 「不安全」? – Tushar

+0

我不知道WhatsApp是如何做到的,或許其他人也不知道。也許你可以告訴我們嗎? –

+1

其實,根據我的經驗,WhatsApp *會發送短信驗證賬戶創建。 – kabuko

回答

19

WhatsApp的不發送任何短信給你,它會發送一個短信用自己的手機你自己的號碼。如果您收到短信,一切正常,如果您沒有收到短信,則您不擁有該號碼。這是檢查用戶是否註冊了真實號碼的唯一便宜且簡單的方法。

+0

這意味着用戶必須爲單個SMS付費嗎? 該解決方案的任何已知缺陷? – andreas78

+0

是的,這是正確的。我不知道這個解決方案的任何缺點 – ObAt

+0

我已經閱讀了一下這個,它不是很安全。 看來WhatsApp的註冊過程並不安全。 幾個假裝成電話號碼所有者的例子。 : -/ – andreas78

1

谷歌Play服務兩個新的API,幫助您獲得用戶的 電話號碼,通過短信驗證它沒有設備權限:在 手機選擇和短信獵犬。

使用手機選擇,以獲得數

的第一步是讓用戶發起短信驗證從 你的應用程序中。您的應用程序可能會提示用戶輸入電話 號碼,您可以使用手機選擇,以使這更容易,使用這樣 代碼:

// Construct a request for phone numbers and show the picker 
private void requestHint() { 
    HintRequest hintRequest = new HintRequest.Builder() 
      .setPhoneNumberIdentifierSupported(true) 
      .build(); 

    PendingIntent intent = Auth.CredentialsApi.getHintPickerIntent(
      apiClient, hintRequest); 
    startIntentSenderForResult(intent.getIntentSender(), 
      RESOLVE_HINT, null, 0, 0, 0); 
} 

的HintRequest建設者告訴播放服務,一個電話號碼 標識是必要的。然後這用於創建並啓動一個意圖, 將向用戶顯示一個播放服務對話框,允許他們選擇他們的電話號碼與應用程序共享。此API不需要 需要任何權限,並顯示 電話或Google帳戶中可供用戶選擇的號碼。

當用戶選擇將返回到E164格式onActivityResult的 應用程序上運行的 最新版本的播放服務的設備的電話號碼。請注意,在某些情況下,根據您的手機的 ,您可能無法獲得電話號碼,因此請務必檢查 憑證是否非空。如果您沒有號碼,則需要 爲您的用戶提供手動輸入方式。

// Obtain the phone number from the result 
@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (requestCode == RESOLVE_HINT) { 
     if (resultCode == RESULT_OK) { 
      Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY); 
      // credential.getId(); <-- E.164 format phone number on 10.2.+ devices 
     } 
    } 
} 

在這一點上,您將有一個電話號碼字符串爲您的用戶。雖然 這很有用,但您可能需要驗證用戶是否擁有此特定號碼,例如允許他們向其他用戶發送或檢索 消息或用此號碼標識自己。

使用SMS驗證API來驗證數

一個簡單的方法,以驗證電話號碼的所有權是通過發送SMS來 數,含有一個時間驗證碼,並且具有它們 輸入到您的應用程序。短信驗證API爲您提供了 的能力,讓應用可以監聽來自其可以自動解析代碼的傳入短信。

要開始,你的應用程序將與代碼SmsRetrieverClient這樣的:

SmsRetrieverClient client = SmsRetriever.getClient(this /* context */); 

Task<Void> task = client.startSmsRetriever(); 

task.addOnSuccessListener(new OnSuccessListener<Void>() { 
    @Override 
    public void onSuccess(Void aVoid) { 
    // successfully started an SMS Retriever for one SMS message 
    } 
}); 

task.addOnFailureListener(new OnFailureListener() { 
    @Override 
    public void onFailure(@NonNull Exception e) { 
    }); 
); 

這很簡單 - 你得到一個短信獵犬客戶端,然後開始 任務吧。該任務有一個關於成功的聽衆以及一個關於 失敗的人。啓動短信提取器後,您需要將 用戶的電話號碼發送到您的服務器,並啓動它的工作流程 生成該消息並將其發送到該號碼。

消息需要以特定方式構建。消息 必須符合SMS消息,因此它不能超過140個字節。它 需要以一個特定的前綴:'<#>'或兩個連續的 零寬度空格字符(U + 200B)開始。有關 的更多信息,請參閱documentation。它必須以 標識您的應用的11個字符的散列結尾,如下所述。

例子:

<#>使用123456作爲示例應用程序驗證碼!

FA + 9qCX9VSu

一次性驗證碼,可以是任何字符串:你可以簡單地 產生一個隨機數。該消息需要以根據此處的過程確定的 的散列結束。谷歌播放服務將 使用這個散列來確定驗證消息適用於哪個應用程序。 您只需要爲您的應用程序包生成一次散列,並且 簽名證書:它不會更改,並且不應由 客戶端應用程序提供。

然後,您的服務器可以使用您的現有的 SMS基礎設施或服務將消息發送到手機。收到此消息後,Google Play服務會播放一條意圖,其中包含 消息的文本。下面的代碼:

public class MySMSBroadcastReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
    if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) { 
     Bundle extras = intent.getExtras(); 
     Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS); 

     switch(status.getStatusCode()) { 
     case CommonStatusCodes.SUCCESS: 
      String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE); 
      break; 
     case CommonStatusCodes.TIMEOUT: 
      break; 
     } 
    } 
    } 
} 

在你獲得額外的廣播接收器的的onReceive,並 從那裏拉狀態。如果狀態顯示消息 已成功收到,您可以從附加信息中提取消息。 從這裏您可以解析出驗證碼並將其發送回 您的服務器以確認電話號碼的所有權。

參考:Effective phone number verification