authentication - 在 Meteor 中通过 SMS 登录和注册过程

标签 authentication meteor login twilio 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>

用户输入他的电话号码并提交表单。然后将 SMS 代码发送到输入的号码。并且出现了一个新表格:
<form onSubmit={ this.submitCode() }>
  <input type='text' size='5' placeholder='Enter code' />
  <input type='submit' value='Sign In'/>
</form>

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

我找到了 Twilio 服务和这个 package看起来这正是我需要的。但我完全不知道如何使用它。

几个月前,我在教程中只尝试了 Meteor 的默认帐户 UI 身份验证方式,但实际上我不知道如何做这些事情,尤其是通过 SMS。我不需要应用程序中的角色之类的东西,我什至不需要用户名、密码和电子邮件。我只需要一个用户基础 _idphone .所以我需要的只是让用户能够登录(第一次登录就是这样注册)。

感谢您的帮助,详细的答案正是我这次所需要的。

最佳答案

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

  • http(直接从您的方法调用 Twilio API)或,
  • accolver:twilio-meteor(您可以尝试使用该包提供的官方 Twilio-Node Helper Library 服务)

  • 接下来,您还应该安装 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);
        }    
    },
    

    发送短信方法:
    '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.');
                }
            }
        );
    }
    

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

    验证短信方法:
    '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");
        }
    },
    

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

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

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

    react 形式:
    您需要在 React JSX 代码容器中呈现类似这样的表单。
    <form className="new-task" onSubmit={this.handleSubmit.bind(this)} >
        <input
            type="text"
            ref="phoneNumberInput"
            placeholder="Enter Phone Number"
        />
    </form>
    

    编写 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
        });    
    }
    

    然后,与上面类似,创建另一个表单让用户输入发送给他们的代码,并将其发送到服务器进行验证,例如
    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
        });    
    }
    

    AuthCodes 集合:
    您需要在文件中定义一个集合并将其导出,以便可以在需要的地方导入。
    export const AuthCodes = new Mongo.Collection('authcodes');
    

    meteor 服务器方法:

    发简讯:
    '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 
        });    
    }
    

    验证码:
    '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;
        }
    }
    

    关于authentication - 在 Meteor 中通过 SMS 登录和注册过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38988074/

    相关文章:

    django - 如何处理django-social-auth引发的异常?

    javascript - 不能在 contenteditable div 中使用空格

    api - 使用 prestashop api 需要用户登录 web 服务

    node.js - DDP、Node 和 Chrome Browserify

    login - Debian 登录循环

    session - 如何确定由于Grails中未接受Cookie导致登录是否失败

    python - 身份验证 token 仅适用于一个 ID

    javascript - 是否可以在没有服务器的情况下对 Microsoft Graph 进行身份验证?

    php - 如何防止不同设备同时登录同一个账号?

    javascript - meteor 辅助变量去除重复的相邻空格