使用egg.js实现手机、验证码注册的项目实践

目录
  • 手机号注册、验证码校验
    • app/contrpoller/pass.js
    • mode/user.js
  • router.js 路由配置
  • service.js
    • 获取验证码
  • sendmsg.js
    • 发送短信验证码

手机号注册、验证码校验

app/contrpoller/pass.js

'use strict';
const Controller = require('egg').Controller;
class PassController extends Controller {
 //登录
  async login() {
    await this.ctx.render('pass/login.html');
  }
  async getCode(){
    const { ctx,service } = this;
    const captcha=await service.tools.verify(); /* 获取服务里面返回的生成的验证码信息 */
    this.ctx.session.identify_code=captcha.text;  /* 验证码上面的信息,文字内容存放到session里面 */
    ctx.response.type = 'image/svg+xml';  /* 返回的生成的验证码的格式 */
    ctx.body=captcha.data;  /* 给页面返回一张图片 */
  }
   //注册第一步 输入手机号
  async registerStep1() {
    await this.ctx.render('pass/register_step1.html');
  }
  //注册第二步  验证码验证码是否正确
  async registerStep2() {
    var sign=this.ctx.request.query.sign;
    var identify_code=this.ctx.request.query.identify_code;
    var add_day=await this.service.tools.getDay();         //年月日
    var userTempResult=await this.ctx.model.User.UserTemp.find({"sign":sign,add_day:add_day});
    if(userTempResult.length==0){
      this.ctx.redirect('/register/registerStep1');
    }else{
      await this.ctx.render('pass/register_step2.html',{
        sign:sign,
        phone:userTempResult[0].phone,
        identify_code:identify_code
      });
    }
  }
  //注册第三步  输入密码
  async registerStep3() {
    var sign = this.ctx.request.query.sign;
    var phone_code = this.ctx.request.query.phone_code;
    var msg = this.ctx.request.query.msg || '';
    var add_day = await this.service.tools.getDay();         //年月日
    var userTempResult = await this.ctx.model.User.UserTemp.find({ "sign": sign, add_day: add_day });
    if (userTempResult.length == 0) {
      this.ctx.redirect('/register/registerStep1');
    } else {
      await this.ctx.render('pass/register_step3.html', {
        sign: sign,
        phone_code: phone_code,
        msg: msg
      });
    }
  }

    //完成注册  post
  async doRegister() {
    this.ctx.body='完成注册';
  }

  //发送短信验证码
  async sendCode(){
    var phone=this.ctx.request.query.phone;
    var identify_code=this.ctx.request.query.identify_code;  //用户输入的验证码
    if(identify_code.toLowerCase()!=this.ctx.session.identify_code.toLowerCase()){
        this.ctx.body={
          success:false,
          msg:'输入的图形验证码不正确'
        }
    }else{
        //判断手机格式是否合法
        var reg =/^[\d]{11}$/;
        if(!reg.test(phone)){
          this.ctx.body={
            success:false,
            msg:'手机号不合法'
          }
        }else{
          var add_day=await this.service.tools.getDay();         //年月日
          var add_time=await this.service.tools.getTime();
          var sign=await this.service.tools.md5(phone+add_day);  //签名
          var ip=this.ctx.request.ip.replace(/::ffff:/, '');     //获取客户端ip
          var phone_code=await this.service.tools.getRandomNum();  //发送短信的随机码
          var userTempResult=await this.ctx.model.User.UserTemp.find({"sign":sign,add_day:add_day});
          //1个ip 一天只能发10个手机号
          var ipCount=await this.ctx.model.User.UserTemp.find({"ip":ip,add_day:add_day}).count();
          if(userTempResult.length>0){
              if(userTempResult[0].send_count<6 && ipCount<10){                     //执行发送
                    var send_count=userTempResult[0].send_count+1;
                    await this.ctx.model.User.UserTemp.updateOne({"_id":userTempResult[0]._id},{"send_count":send_count,'add_time':add_time});
                    this.ctx.session.phone_code=phone_code;
                    //发送短信
                    this.service.sendmsg.send(phone,phone_code);
                    console.log('---------------------------------');
                    console.log(phone_code,ipCount);
                    this.ctx.body={
                      success:true,
                      msg:'短信发送成功',
                      sign:sign,
                    }
              }else{
                    this.ctx.body={"success":false,msg:'当前手机号码发送次数达到上限,明天重试'};
              }
          }else{
              var userTmep=new this.ctx.model.User.UserTemp({
                  phone,
                  add_day,
                  sign,
                  ip,
                  send_count:1
              });
              userTmep.save();
              this.ctx.session.phone_code=phone_code;
              //发送短信
              this.service.sendmsg.send(phone,phone_code);
              this.ctx.body={
                success:true,
                msg:'短信发送成功',
                sign:sign,
              }
          }
        }
    }
  }

  //验证验证码
  async validatePhoneCode(){
    var sign=this.ctx.request.query.sign;
    var phone_code=this.ctx.request.query.phone_code;
    var add_day=await this.service.tools.getDay();         //年月日
    if(this.ctx.session.phone_code!=phone_code){
      this.ctx.body={
        success:false,
        msg:'您输入的手机验证码错误'
      }
    }else{
      var userTempResult=await this.ctx.model.User.UserTemp.find({"sign":sign,add_day:add_day});
      if(userTempResult.length<=0){
        this.ctx.body={
          success:false,
          msg:'参数错误'
        }
      }else{
        //判断验证码是否超时
        var nowTime=await this.service.tools.getTime();
        if((userTempResult[0].add_time-nowTime)/1000/60>30){
          this.ctx.body={
            success:false,
            msg:'验证码已经过期'
          }
        }else{
          //用户表有没有当前这个手机号        手机号有没有注册
          var userResult=await this.ctx.model.User.User.find({"phone":userTempResult[0].phone});
          if(userResult.length>0){
            this.ctx.body={
              success:false,
              msg:'此用户已经存在'
            }
          }else{
            this.ctx.body={
              success:true,
              msg:'验证码输入正确',
              sign:sign
            }
          }
        }
      }
    }
  }

  //完成注册  post
  async doRegister() {
    var sign=this.ctx.request.body.sign;
    var phone_code=this.ctx.request.body.phone_code;
    var add_day=await this.service.tools.getDay();         //年月日
    var password=this.ctx.request.body.password;
    var rpassword=this.ctx.request.body.rpassword;
    var ip=this.ctx.request.ip.replace(/::ffff:/, '') ;
    if(this.ctx.session.phone_code!=phone_code){
      //非法操作
      this.ctx.redirect('/pass/registerStep1');
    }
    var userTempResult=await this.ctx.model.User.UserTemp.find({"sign":sign,add_day:add_day});
    if(userTempResult.length==0){
      //非法操作
      this.ctx.redirect('/pass/registerStep1');
    }else{
      //传入参数正确 执行增加操作
      if(password.length<6 || password!=rpassword){
        var msg='密码不能小于6位并且密码和确认密码必须一致';
        this.ctx.redirect('/register/registerStep3?sign='+sign+'&phone_code='+phone_code+'&msg='+msg);
      }else{
          var userModel=new this.ctx.model.User.User({
          phone:userTempResult[0].phone,
          password:await this.service.tools.md5(password),
          last_ip:ip
        });
        //保存用户
        var userReuslt=await userModel.save();
        if(userReuslt){
          //跳转到登入页面
          this.ctx.redirect('/login');
        }
        // if(userReuslt){
        //   //获取用户信息
        //   var userinfo=await this.ctx.model.User.User.find({"phone":userTempResult[0].phone},'_id phone last_ip add_time email status');
        //   //用户注册成功以后默认登录
        //   //cookies 安全      加密
        //   this.service.cookies.set('userinfo',userinfo[0]);
        //   this.ctx.redirect('/');
        // }
      }
    }
  }
}
module.exports = PassController;

mode/user.js

module.exports = app => {
    const mongoose = app.mongoose;
    const Schema = mongoose.Schema;
    var d=new Date();
    const User = new Schema({
      /*
        ip:ip,
              password:password,
              phone:phone,
              add_time:add_time,
              last_ip:last_ip,
              status:status
      */
      password:{type:String },
      phone: {type:Number },
      last_ip:{type:String },
      add_time: {
        type:Number,
        default: d.getTime()
      },
      email:{type:String },
      status: {
        type:Number,
        default: 1
      }
    });
    return mongoose.model('User', User,'user');
};

router.js 路由配置

module.exports = app => {
    const { router, controller } = app;

    //普通用户登入
    router.get('/user/verify', controller.admin.base.verify);
    //用户注册登录
    router.get('/login',controller.default.pass.login);
    router.get('/register/registerStep1', controller.default.pass.registerStep1);
    router.get('/register/registerStep2', controller.default.pass.registerStep2);
    router.get('/register/registerStep3', controller.default.pass.registerStep3);
    //用户点击注册
    router.get('/pass/sendCode', controller.default.pass.sendCode);
    //注册前台验证码
    router.get('/verify', controller.default.pass.getCode);
    //注册验证手机短信码
    router.get('/pass/validatePhoneCode', controller.default.pass.validatePhoneCode);
    //注册最后一步,输入账号和密码
    router.post('/pass/doRegister', controller.default.pass.doRegister);
};

service.js

获取验证码

'use strict';
//引入node.js  生成svg图形验证码模块
const svgCaptcha = require('svg-captcha');
const Service = require('egg').Service;
const md5 = require('md5');
const path=require('path');
const sd = require('silly-datetime');
const mkdirp = require('mz-modules/mkdirp');
const Jimp = require("jimp");  //生成缩略图的模块
class ToolsService extends Service {
  async verify() {  /* 生成验证码 */
    const captcha = svgCaptcha.create(
      {
        size:4,     //验证码图片里面的一些信息
        fontSize: 50,
        width: 100,
        height:40,
        background: "#cc9966"
      });
    return  captcha;
  }
  /*生成随机的4位数字*/
  async getRandomNum(){
      let num='';
      for(var i=0;i<4;i++){
        num+=Math.floor(Math.random()*10)
      }
      return num;
    }
  /*生成当年当月当天的数字*/
  async getDay(){
    const day=sd.format(new Date(), 'YYYYMMDD');
    return day;
  }
  /* 生成当前时间*/
  async getTime(){
     var date=new Date();
     return date.getTime();
  }
  async md5(string){   /* 封装一个md5加密*/
        return  md5(string);
  }
  async getFocusAddPath(filename){
      /*
          1: 获取传递过来的图片的名字, 获取当前日期 silly-datetime模块
          2: 根据当前的日期,设置对应的文件夹,如果存在就不设置,不存在就设置 mz-modules模块
      */
     const day=sd.format(new Date(), 'YYYYMMDD');
     let dir=path.join(this.config.uploadDir,day);
     await mkdirp(dir);
     const date=new Date();
     let d=await date.getTime();   /*毫秒数*/
     /*图片保存的路径*/
     let uploadDir=path.join(dir,d+path.extname(filename));
     /*app\public\admin\upload\20190614\1560520826971.png */
    return {
      uploadDir:uploadDir,
      /* 保存到数据库的地址 */
      saveDir:uploadDir.slice(3).replace(/\\/g,'/')
    }
  }
  //生成缩略图的公共方法
  async jimpImg(target){
    //上传图片成功以后生成缩略图
    Jimp.read(target, (err, lenna) => {
      if (err) throw err;
      lenna.resize(200, 200) // resize
        .quality(90) // set JPEG quality
        .write(target+'_200*200'+path.extname(target)); // save
      lenna.resize(400, 400) // resize
        .quality(90) // set JPEG quality
        .write(target+'_400*400'+path.extname(target)); // save
    });
  }

}
module.exports = ToolsService;

sendmsg.js

发送短信验证码

(需要上云片网购买短信服务)

'use strict';
const Service = require('egg').Service;
var https = require('https');
var qs = require('querystring');
class SendmsgService extends Service {
  async send(mobile,code) {
    //apikey自己到云片网上面去买。
    var apikey = '092******************eec';
    // 修改为您要发送的手机号码,多个号码用逗号隔开
    var mobile = mobile;
    // 修改为您要发送的短信内容
    var text = '【java学习网】您的验证码是'+code;
    // 智能匹配模板发送https地址
    var sms_host = 'sms.yunpian.com';
    var send_sms_uri = '/v2/sms/single_send.json';
    // 指定模板发送接口https地址
    send_sms(send_sms_uri,apikey,mobile,text);
    function send_sms(uri,apikey,mobile,text){
        var post_data = {
        'apikey': apikey,
        'mobile':mobile,
        'text':text,
        };//这是需要提交的数据
        var content = qs.stringify(post_data);
        post(uri,content,sms_host);
    }
    function post(uri,content,host){
        var options = {
            hostname: host,
            port: 443,
            path: uri,
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
            }
        };
        var req = https.request(options, function (res) {
            // console.log('STATUS: ' + res.statusCode);
            // console.log('HEADERS: ' + JSON.stringify(res.headers));
            res.setEncoding('utf8');
            res.on('data', function (chunk) {
                 console.log('BODY: ' + chunk);     //如果错误  自己把它写入一个日志
            });
        });
        //console.log(content);
        req.write(content);
        req.end();
    }

  }
}
module.exports = SendmsgService;

到此这篇关于使用egg.js实现手机、验证码注册的项目实践的文章就介绍到这了,更多相关egg.js 手机验证码注册内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • egg.js的基本使用和调用数据库的方法示例

    首先,整个项目的创建命令: npm i egg-init -g //安装egg egg-init egg-example --type=simple //初始化一个egg模板例子 后面的type跟的是模板类型这里是简单的 cd egg-example//进入例子 npm i //安装依赖 可以去官方教程查看基本配置的讲解. 直接说使用,简单看过Egg的文档,官方文档对于入门还是很实用的,再配合一些别人的攻略很容易入门上手就可以使用. 首先router.js: 'use strict'; /**

  • Egg框架的功能、原理,以及基本使用方法概述 原创

    概述 Egg是一款基于Koa框架的企业级Node.js框架,其主要目标是帮助团队和开发者快速构建可维护和易扩展的应用程序. Egg框架的主要功能包括: 1. 基于Koa框架,提供了丰富的插件机制,可以轻松集成常用的中间件和工具.2. 支持异步编程,通过Promises和async/await来实现流程控制.3. 开箱即用的配置加载和覆盖能力,可根据环境变量自动切换不同的配置.4. 内置路由系统,支持URL参数,RESTful风格的API设计.5. 完善的插件生态系统,涵盖了日志.数据库.缓存等各

  • 为何从eggjs升级到midwayjs的原因详解

    目录 引言 midwayjs简介 为什么不是nestjs IoC机制与装饰器 总结 引言 今天突然发现园区的银杏叶突然全黄了,想起来两周前到临安去玩的时候还是青黄交加的一片呢.虽然最近温度似乎也没怎么降,但从最近路边的落叶上看,真的是深秋了,可能就再需要一场秋雨,杭州就要开始入冬了吧 最近笔者在维护一个旧的node项目,项目基于eggjs开发的,数据库是mysql,缓存redis,消息中间件用的是rocketMQ.项目早期用的是js,在改造typescript的过程中,越来越感觉到eggjs对t

  • React+EggJs实现断点续传的示例代码

    技术栈 前端用了React,后端则是EggJs,都用了TypeScript编写. 断点续传实现原理 断点续传就是在上传一个文件的时候可以暂停掉上传中的文件,然后恢复上传时不需要重新上传整个文件. 该功能实现流程是先把上传的文件进行切割,然后把切割之后的文件块发送到服务端,发送完毕之后通知服务端组合文件块. 其中暂停上传功能就是前端取消掉文件块的上传请求,恢复上传则是把未上传的文件块重新上传.需要前后端配合完成. 前端实现 前端主要分为:切割文件.获取文件MD5值.上传切割后的文件块.合并文件.暂

  • Egg.js 中 AJax 上传文件获取参数的方法

    依赖 formidable 代码 前端 <fieldset style="margin: 20px; padding: 20px;"> <legend>单文件,Ajax</legend> <form id="form3"> <div> <input type="text" id="customName" placeholder="自定义文件名"

  • Nodejs环境Eggjs加签验签示例代码

    加签验签概念 加签: 用Hash函数把原始报文生成报文摘要,然后用私钥对这个摘要进行加密,就得到这个报文对应的数字签名.「注意啦,加签过程要包含一些特殊的私有的东西,比如个人私钥.」 通常来说呢,请求方会把「数字签名和报文原文」一并发送给接收方. 验签: 接收方拿到原始报文和数字签名后,用「同一个Hash函数」从报文中生成摘要A.另外,用对方提供的公钥对数字签名进行解密,得到摘要B,对比A和B是否相同,就可以得知报文有没有被篡改过. 如下使用Egg.js示例代码 // 获取签名 router.p

  • KOA+egg.js集成kafka消息队列的示例

    Egg.js : 基于KOA2的企业级框架 Kafka:高吞吐量的分布式发布订阅消息系统 本文章将集成egg + kafka + mysql 的日志系统例子 系统要求:日志记录,通过kafka进行消息队列控制 思路图: 这里消费者和生产者都由日志系统提供 λ.1 环境准备 ①Kafka 官网下载kafka后,解压 启动zookeeper: bin/zookeeper-server-start.sh config/zookeeper.properties 启动Kafka server 这里conf

  • vue+egg+jwt实现登录验证的示例代码

    原理:vue前端登录,提交账号密码给egg后端,后端比对信息后,使用jsonwebtoken对用户信息进行签名生成token,之后通过cookie返回给vue前端,前端需要使用token里的信息就使用js-base64进行token第二段解码即可. vue前端路由跳转,进入路由前置守卫检测cookie中的token是否存在,不存在(已过期)则跳转登录,否则继续执行,然后在http拦截器里请求时存在token请求头带上token,后端未得到header则返回错误码,得到则用jsonwebtoken

  • egg.js的基本使用实例

    目录 安装egg.js 写第一个api接口 创建控制器 编写路由 关闭csrf开启跨域 数据库 配置和创建迁移文件 创建数据迁移表 模型 创建模型 错误和异常处理 中间件 参数验证 安装egg.js 全局切换镜像: npm config set registry https://registry.npm.taobao.org 我们推荐直接使用脚手架,只需几条简单指令,即可快速生成项目(npm >=6.1.0): mkdir egg-example && cd egg-example

  • 关于自定义Egg.js的请求级别日志详解

    Egg.js 是什么? Egg.js 为企业级框架和应用而生,我们希望由 Egg.js 孕育出更多上层框架,帮助开发团队和开发人员降低开发和维护成本. 注:Egg.js 缩写为 Egg 背景 组织为了更好的对各个业务的请求日志进行统一的分析,制定了统一的日志打印规范,比如: [time][processId][traceId][userid] Hello World.... 统一格式之后,业务现有业务的日志工具打印出来的格式是无法满足该规范的,所以我们需要对此进行改造. 我们前端目前Node中间

随机推荐