首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防火墙短信验证/认证

防火墙短信验证/认证
EN

Stack Overflow用户
提问于 2016-04-18 13:02:03
回答 4查看 50.4K关注 0票数 33

对于一个客户端项目,我正在创建一个简单的混合应用程序,它提供一个非常简单的功能,但是流量很高。这个应用程序通常不需要后端,因为它非常简单,而且firebase似乎是该项目的完美解决方案。

我唯一坚持的部分是使用Firebase的SMS验证/身份验证。然而,在进行了大量的谷歌搜索和文档阅读之后,我开始意识到,要做到这一点并没有什么简单的方法。下面是我到目前为止研究的内容:

  1. Fabric.io数字有一个很好的JS,但是由于某种原因,火基和数字不能很好地结合在一起:https://groups.google.com/forum/#!topic/firebase-talk/sB7lPuyCVBQ
  2. Facebook帐户工具包 --就在一周前,Facebook发布了一套新的短信验证和认证工具包,尽管它仍然觉得自己有着与fabric.io数字相同的问题,至少在被证明并非如此之前。
  3. Twilio / Nexmo通过NodeJS --它们都是具有优秀JS的史诗式服务,但据我所知,这需要一个单独的后端服务器来处理JWT令牌交换。而这本身就是另一台服务器,它将成为高流量时的瓶颈,以及另一个安全漏洞,客户端团队将不得不单独管理。不是最令人愉快的。
  4. Twilio / Nexmo & Auth0 --到目前为止,这似乎是最好的选择,在这种情况下,身份验证和用户管理由Auth0来处理,但是,考虑到twilio或nexmo和auth0都是付费解决方案,这种解决方案很快就会变得昂贵。并不是说我是一个廉价的人,我希望东西能免费工作,但考虑到它只是为了转发令牌,我觉得这是一个非常昂贵的额外步骤。见:来自地狱的客户
  5. 我记得在某个地方读过这样的建议,比如把电话号码作为电子邮件发送到防火墙上,比如: 123-456-7890@example.com,并使用通过sms发送的安全代码作为密码,这听起来非常粗略,原因有很多。

通常在混合移动应用程序中,它们或JS的非本地特性是罪魁祸首,但第一次(至少对我来说)感觉并非如此。在这一点上,我认为Firebase不是一个有效的选择,但是在开始研究AWS并为客户端设置一个完整的后端之前,我想最后一次询问社区中充满爱心和关爱的成员。

除了中间服务/没有后端服务器之外,还有其他方法来处理这种类型的身份验证吗?有人有使用这些解决方案的经验吗?

更新:2017年5月

电话验证和身份验证现在在Firebase中本机可用。见下面我自己贴出的答案。

更新:2017年4月

Firebase现在本机支持云函数。现在,您可以在不设置任何服务器的情况下使用云函数来完成这一任务和更多的任务。

更新:2017年10月

Fabric.io和Firebase合作并集成了Firebase电话身份验证中的数字,并为Fabric推出了更多功能。

EN

Stack Overflow用户

发布于 2017-08-03 22:57:20

代码语言:javascript
复制
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseException;
import com.google.firebase.FirebaseTooManyRequestsException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;

import java.util.concurrent.TimeUnit;

public class PhoneAutenticationService {
public PhoneAutenticationService(Activity activity,FirebaseAuth auth) {
    this.activity = activity;
    this.mAuth = auth;
    setupCallback();
}

private static final String TAG = PhoneAutenticationService.class.getSimpleName();

private Activity activity;
private String verificationCode;
private static final String KEY_VERIFY_IN_PROGRESS = "key_verify_in_progress";

private static final int STATE_INITIALIZED = 1;
private static final int STATE_CODE_SENT = 2;
private static final int STATE_VERIFY_FAILED = 3;
private static final int STATE_VERIFY_SUCCESS = 4;
private static final int STATE_SIGNIN_FAILED = 5;
private static final int STATE_SIGNIN_SUCCESS = 6;

// [START declare_auth]
private FirebaseAuth mAuth;
// [END declare_auth]

private boolean mVerificationInProgress = false;
private String mVerificationId;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private PhoneAuthProvider.ForceResendingToken mResendToken;

protected void onSaveInstanceState(Bundle outState) {
    outState.putBoolean(KEY_VERIFY_IN_PROGRESS, mVerificationInProgress);
}

protected void onRestoreInstanceState(Bundle savedInstanceState) {
    mVerificationInProgress = savedInstanceState.getBoolean(KEY_VERIFY_IN_PROGRESS);
}


// [START on_start_check_user]
public void onStart(EditText mPhoneNumberField) {
    // Check if user is signed in (non-null) and update UI accordingly.
    FirebaseUser currentUser = mAuth.getCurrentUser();
    updateUI(currentUser);
    // [START_EXCLUDE]
    if (mVerificationInProgress && validatePhoneNumber(mPhoneNumberField)) {
        startPhoneNumberVerification(mPhoneNumberField.getText().toString());
    }
    // [END_EXCLUDE]
}
// [END on_start_check_user]

private void setupCallback(){
    mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

        @Override
        public void onVerificationCompleted(PhoneAuthCredential credential) {
            // This callback will be invoked in two situations:
            // 1 - Instant verification. In some cases the phone number can be instantly
            //     verified without needing to send or enter a verification code.
            // 2 - Auto-retrieval. On some devices Google Play services can automatically
            //     detect the incoming verification SMS and perform verificaiton without
            //     user action.
            Log.d(TAG, "onVerificationCompleted:" + credential);
            // [START_EXCLUDE silent]
            mVerificationInProgress = false;
            // [END_EXCLUDE]

            // [START_EXCLUDE silent]
            // Update the UI and attempt sign in with the phone credential
            updateUI(STATE_VERIFY_SUCCESS, credential);
            // [END_EXCLUDE]
            signInWithPhoneAuthCredential(credential);
        }

        @Override
        public void onVerificationFailed(FirebaseException e) {
            // This callback is invoked in an invalid request for verification is made,
            // for instance if the the phone number format is not valid.
            Log.w(TAG, "onVerificationFailed", e);
            // [START_EXCLUDE silent]
            mVerificationInProgress = false;
            // [END_EXCLUDE]

            if (e instanceof FirebaseAuthInvalidCredentialsException) {
                // Invalid request
                // [START_EXCLUDE]
                Toast.makeText(activity,"Invalid phone number.",Toast.LENGTH_SHORT).show();
                // [END_EXCLUDE]
            } else if (e instanceof FirebaseTooManyRequestsException) {
                // The SMS quota for the project has been exceeded
                // [START_EXCLUDE]
                Toast.makeText(activity,"Quota exceeded.",Toast.LENGTH_SHORT).show();

                // [END_EXCLUDE]
            }

            // Show a message and update the UI
            // [START_EXCLUDE]
            updateUI(STATE_VERIFY_FAILED);
            // [END_EXCLUDE]
        }

        @Override
        public void onCodeSent(String verificationId,
                               PhoneAuthProvider.ForceResendingToken token) {
            // The SMS verification code has been sent to the provided phone number, we
            // now need to ask the user to enter the code and then construct a credential
            // by combining the code with a verification ID.
            Log.d(TAG, "onCodeSent:" + verificationId);
            Toast.makeText(activity,"onCodeSent:" + verificationId,Toast.LENGTH_SHORT).show();
            verificationCode = verificationId;
            // Save verification ID and resending token so we can use them later
            mVerificationId = verificationId;
            setVerificationCode(verificationId);
            mResendToken = token;

            // [START_EXCLUDE]
            // Update UI
            updateUI(STATE_CODE_SENT);
            // [END_EXCLUDE]
        }

    };
}


public void startPhoneNumberVerification(String phoneNumber) {
    // [START start_phone_auth]
    PhoneAuthProvider.getInstance().verifyPhoneNumber(
            phoneNumber,        // Phone number to verify
            60,                 // Timeout duration
            TimeUnit.SECONDS,   // Unit of timeout
            activity,               // Activity (for callback binding)
            mCallbacks);        // OnVerificationStateChangedCallbacks
    // [END start_phone_auth]

    mVerificationInProgress = true;
}



public void verifyPhoneNumberWithCode(String verificationId, String code) {
    // [START verify_with_code]
    PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);

    // [END verify_with_code]
    signInWithPhoneAuthCredential(credential);
}

// [START resend_verification]
public void resendVerificationCode(String phoneNumber,
                                   PhoneAuthProvider.ForceResendingToken token) {
    PhoneAuthProvider.getInstance().verifyPhoneNumber(
            phoneNumber,        // Phone number to verify
            60,                 // Timeout duration
            TimeUnit.SECONDS,   // Unit of timeout
            activity,               // Activity (for callback binding)
            mCallbacks);        // resending
    // [END start_phone_auth]
}
// [END resend_verification]

// [START sign_in_with_phone]
public void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(activity, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInWithCredential:success");
                        Toast.makeText(activity,"signInWithCredential:success",Toast.LENGTH_SHORT).show();
                        FirebaseUser user = task.getResult().getUser();
                        // [START_EXCLUDE]
                        updateUI(STATE_SIGNIN_SUCCESS, user);
                        // [END_EXCLUDE]
                    } else {
                        // Sign in failed, display a message and update the UI
                        Log.w(TAG, "signInWithCredential:failure", task.getException());
                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            // The verification code entered was invalid
                            // [START_EXCLUDE silent]
                            Toast.makeText(activity,"Invalid code.",Toast.LENGTH_SHORT).show();
                            // [END_EXCLUDE]
                        }
                        // [START_EXCLUDE silent]
                        // Update UI
                        updateUI(STATE_SIGNIN_FAILED);
                        // [END_EXCLUDE]
                    }
                }
            });
}
// [END sign_in_with_phone]


public void signOut() {
    mAuth.signOut();
    updateUI(STATE_INITIALIZED);
}

private void updateUI(int uiState) {
    updateUI(uiState, mAuth.getCurrentUser(), null);
}

public void updateUI(FirebaseUser user) {
    if (user != null) {
        updateUI(STATE_SIGNIN_SUCCESS, user);
    } else {
        updateUI(STATE_INITIALIZED);
    }
}

private void updateUI(int uiState, FirebaseUser user) {
    updateUI(uiState, user, null);
}

private void updateUI(int uiState, PhoneAuthCredential cred) {
    updateUI(uiState, null, cred);
}

private void updateUI(int uiState, FirebaseUser user, PhoneAuthCredential cred) {
    switch (uiState) {
        case STATE_INITIALIZED:
            // Initialized state, show only the phone number field and start button
            Toast.makeText(activity,"Initialized state",Toast.LENGTH_SHORT).show();
            break;
        case STATE_CODE_SENT:
            // Code sent state, show the verification field, the
            Toast.makeText(activity,"Code sent state",Toast.LENGTH_SHORT).show();

            break;
        case STATE_VERIFY_FAILED:
            // Verification has failed, show all options
            Toast.makeText(activity,"Verification has failed",Toast.LENGTH_SHORT).show();

            break;
        case STATE_VERIFY_SUCCESS:
            // Verification has succeeded, proceed to firebase sign in
            Toast.makeText(activity,"Verification has succeeded",Toast.LENGTH_SHORT).show();

            // Set the verification text based on the credential
            if (cred != null) {
                if (cred.getSmsCode() != null) {
                    //mVerificationField.setText(cred.getSmsCode());
                } else {
                    Toast.makeText(activity,"Invalid verification code.",Toast.LENGTH_SHORT).show();
                }
            }

            break;
        case STATE_SIGNIN_FAILED:
            // No-op, handled by sign-in check
            Toast.makeText(activity,"Sign in failed",Toast.LENGTH_SHORT).show();

            break;
        case STATE_SIGNIN_SUCCESS:
            // Np-op, handled by sign-in check
            Toast.makeText(activity,"Sign in sucesssss!!!!",Toast.LENGTH_SHORT).show();
            break;
    }

    if (user == null) {
        // Signed out

    } else {
        // Signed in
    }
}


public boolean validatePhoneNumber(EditText mPhoneNumberField) {
    String phoneNumber = mPhoneNumberField.getText().toString();
    if (TextUtils.isEmpty(phoneNumber) || phoneNumber.length()>10 || phoneNumber.length()<9) {
        Toast.makeText(activity,"Invalid phone number.",Toast.LENGTH_SHORT).show();
        return false;
    }

    return true;
}

public PhoneAuthProvider.OnVerificationStateChangedCallbacks getmCallbacks() {
    return mCallbacks;
}

public PhoneAuthProvider.ForceResendingToken getmResendToken() {
    return mResendToken;
}

public FirebaseAuth getmAuth() {
    return mAuth;
}

public String getVerificationCode() {
    return verificationCode;
}

public void setVerificationCode(String verificationCode) {
    this.verificationCode = verificationCode;
}

}

在您的活动中,初始化Firebase auth和监听器

代码语言:javascript
复制
 mAuth = FirebaseAuth.getInstance();
    mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null) {
                Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
            } else {
                Log.d(TAG, "onAuthStateChanged:signed_out");
            }
            // ...
        }
    };


    //init all auth process
    phoneAutenticationService = new PhoneAutenticationService(this,mAuth);

 @Override
public void onStart() {
    super.onStart();
    mAuth.addAuthStateListener(mAuthListener);
    getActivity().registerReceiver(smsBroadcastReceiver, filter);// define e broadcast receiver to intercept a sms verification code
}

@Override
public void onStop() {
    super.onStop();
    if (mAuthListener != null) {
        mAuth.removeAuthStateListener(mAuthListener);sms code
    }
    getActivity().unregisterReceiver(smsBroadcastReceiver);

}

最后调用firebase方法进行身份验证。

代码语言:javascript
复制
public void startAuthenticationByPhone(){
    if (!validatePhoneNumber(phoneInput)) {
        return;
    }
    startPhoneNumberVerification(phoneInput.getText().toString());

}......
票数 2
EN
查看全部 4 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36694791

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档