在Meteor中通过短信登录和注册过程

One*_*sor 4 authentication login twilio meteor meteor-accounts

我需要在我的Meteor应用程序中进行SMS身份验证.

假设我有一个简单的形式(在React风格中,因为我在前端使用React):

<form onSubmit={ this.submitPhone() }>
  <input type='text' size='10' placeholder='Your phone here' />
  <input type='submit' value='Send me a code'/>
</form>
Run Code Online (Sandbox Code Playgroud)

用户输入他的电话号码并提交表格.之后,将SMS代码发送到输入的号码.并出现一个新表格:

<form onSubmit={ this.submitCode() }>
  <input type='text' size='5' placeholder='Enter code' />
  <input type='submit' value='Sign In'/>
</form>
Run Code Online (Sandbox Code Playgroud)

如果用户正确输入了他的代码,那么Meteor应该知道用户已登录(我认为有一些_id).如果代码不正确,则会显示错误消息.

我发现Twilio服务和这个包,看起来它正是我需要的.但我根本不知道如何使用它.

几个月前我在教程中尝试过Meteor的默认Accounts UI方式,但实际上我不知道如何做这些事情,尤其是通过短信.我不需要像我的应用程序中的角色这样的东西,我甚至不需要用户名,密码和电子邮件.我只需要有一个用户基础_id和phone.所以我需要的是让用户能够登录(第一次登录是以这种方式注册).

感谢您的帮助,这次我需要一个详细的答案.

ryd*_*der 6

首先,您需要安装以下软件包之一:

接下来,您还应该安装okland:accounts-phone软件包以帮助启用通过电话号码登录.他们的GitHub提供了关于如何设置的简单说明.

密码

我强烈建议使用密码和电话号码创建用户帐户,因为它是一个很好的安全功能,默认情况下也需要Meteor Accounts软件包.

验证过程

我将使用服务器端Meteor方法给出一个示例,对于前端,您可以相应地编写React处理程序.

这个例子将使用HTTP包,在你的代码中,如果你愿意,可以修改它以包含其他包装软件包,如twilio-meteor.

第1步: 注册您的用户并发送验证短信.

createNewUser方法:

'createNewUser': function (password, phoneNumber) {
    var min = 10000;
    var max = 99999;
    var random = Math.floor(Math.random() * (max - min + 1)) + min;

    var verified = Meteor.users.find({username: phoneNumber}).fetch();
    if (verified.length > 0) {
        if (verified.length == 1 && verified[0].profile.isMobileVerified == 'NO') {
            Meteor.users.remove({username: phoneNumber});
            var user = {username: phoneNumber, password: password, profile: { randomSms: random, isMobileVerified: 'NO' }};
            Meteor.call("sendSMS", random, phoneNumber);
            Accounts.createUser(user);
            return returnSuccess('Successfully created', phoneNumber);
        } else {
            return returnFaliure('Mobile number already exists', phoneNumber);
        }
    } else {
        var user = {username: phoneNumber, password: password, profile: { randomSms: random, isMobileVerified: 'NO' }};
        Meteor.call("sendSMS", random, phoneNumber);
        Accounts.createUser(user);
        return returnSuccess('Successfully created', phoneNumber);
    }    
},
Run Code Online (Sandbox Code Playgroud)

sendSMS方法:

'sendSMS': function (code, mobile) {
    console.log(mobile);
    HTTP.call(
        "POST",
        'https://api.twilio.com/{yyyy-dd-mm}/Accounts/' + 
        '{TWILIO_APPKEY}' + '/SMS/Messages.json', {
            params: {
                From: '+11234567890',
                To: mobile,
                Body: "Greetings! Your OTP is " + code
            },
            auth: '{TWILIO_APPKEY}' + ':' + '{TWILIO_PASSWORD}'
        },
        // Print error or success to console
        function (error) {
            if (error) {
                console.log(error);
            }
            else {
                console.log('SMS sent successfully.');
            }
        }
    );
}
Run Code Online (Sandbox Code Playgroud)

第2步: 向用户询问验证码并检查用户输入的代码

verifySMS方法:

'verifySMS': function (code, userid) {
    console.log(userid);
    var sms = Meteor.users.findOne({username: userid}).profile.randomSms;
    if (sms == code) {
        Meteor.users.update({username: userid}, {
            $set: {"profile.isMobileVerified": "YES", "profile.randomSms": "--"}
        });
        return returnSuccess("Yes");
    } else {
        return returnSuccess("No");
    }
},
Run Code Online (Sandbox Code Playgroud)

第3步: 从您的React代码处理,如果代码匹配,批准用户,否则显示相应的错误消息.


通过OP处理特定用例的更新:( 示例表示React代码)

要在登录前每次通过SMS OTP代码对用户进行身份验证,您需要在每次用户尝试登录时使用sendSMS方法,在存储的AuthCodes集合中更新它,每次验证代码,并相应地处理案例.

React Form: 您需要在反应JSX代码容器中呈现这样的表单.

<form className="new-task" onSubmit={this.handleSubmit.bind(this)} >
    <input
        type="text"
        ref="phoneNumberInput"
        placeholder="Enter Phone Number"
    />
</form>
Run Code Online (Sandbox Code Playgroud)

将React函数写入登录用户:

handleSubmit() {
    event.preventDefault();
    // Find the phone number field via the React ref
    const phoneNumber = ReactDOM.findDOMNode(this.refs.phoneNumberInput).value.trim();
    Meteor.call('sendAuthCode', Meteor.userId(), phoneNumber, function(error, result) {
        // Show a popup to user that code has been sent
    });    
}
Run Code Online (Sandbox Code Playgroud)

然后,与上面类似,创建另一个表单以让用户输入发送给他们的代码,并将其发送到服务器进行验证,例如

handleAuthCheck() {
    event.preventDefault();
    // Find the phone number field via the React ref
    const phoneNumber = ReactDOM.findDOMNode(this.refs.phoneNumberInput).value.trim();
    const code = ReactDOM.findDOMNode(this.refs.codeInput).value.trim();
    Meteor.call('verifyAuthCode', Meteor.userId(), phoneNumber, code, function(error, result) {
        // handle result accordingly
        // you need to decide how you are going to login user 
        // you can create a custom module for that if you need to
    });    
}
Run Code Online (Sandbox Code Playgroud)

AuthCodes集合: 您需要在文件中定义集合并将其导出,以便可以在需要时导入.

export const AuthCodes = new Mongo.Collection('authcodes');
Run Code Online (Sandbox Code Playgroud)

流星服务器方法:

发送短信:

'sendAuthCode': function(userId, phoneNumber) {
    var min = 10000;
    var max = 99999;
    var code = Math.floor(Math.random() * (max - min + 1)) + min;
    Meteor.call("sendSMS", code, phoneNumber);
    AuthCodes.insert({ 
        userId: userId, 
        phoneNumber: phoneNumber, 
        code: code 
    });    
}
Run Code Online (Sandbox Code Playgroud)

验证码:

'verifyAuthCode': function(userId, phoneNumber, code) {
    var authCode = AuthCodes.findOne({ phoneNumber: phoneNumber, code: code })   // You can also add userId check for added verification
    if(typeof authCode !== "undefined" && authCode) {
        // verification passed
        return true;
    } else {
        // verification failed
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)