2013-01-17 183 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