使用egg.js實現(xiàn)手機、驗證碼注冊的項目實踐
手機號注冊、驗證碼校驗
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(); /* 獲取服務(wù)里面返回的生成的驗證碼信息 */ ? ? this.ctx.session.identify_code=captcha.text; ?/* 驗證碼上面的信息,文字內(nèi)容存放到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='完成注冊'; ? } ? //發(fā)送短信驗證碼 ? 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(); ?//發(fā)送短信的隨機碼 ? ? ? ? ? var userTempResult=await this.ctx.model.User.UserTemp.find({"sign":sign,add_day:add_day}); ? ? ? ? ? //1個ip 一天只能發(fā)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){ ? ? ? ? ? ? ? ? ? ? //執(zhí)行發(fā)送 ? ? ? ? ? ? ? ? ? ? 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; ? ? ? ? ? ? ? ? ? ? //發(fā)送短信 ? ? ? ? ? ? ? ? ? ? this.service.sendmsg.send(phone,phone_code); ? ? ? ? ? ? ? ? ? ? console.log('---------------------------------'); ? ? ? ? ? ? ? ? ? ? console.log(phone_code,ipCount); ? ? ? ? ? ? ? ? ? ? this.ctx.body={ ? ? ? ? ? ? ? ? ? ? ? success:true, ? ? ? ? ? ? ? ? ? ? ? msg:'短信發(fā)送成功', ? ? ? ? ? ? ? ? ? ? ? sign:sign, ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? ? ? this.ctx.body={"success":false,msg:'當(dāng)前手機號碼發(fā)送次數(shù)達到上限,明天重試'}; ? ? ? ? ? ? ? } ? ? ? ? ? }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; ? ? ? ? ? ? ? //發(fā)送短信 ? ? ? ? ? ? ? this.service.sendmsg.send(phone,phone_code); ? ? ? ? ? ? ? this.ctx.body={ ? ? ? ? ? ? ? ? success:true, ? ? ? ? ? ? ? ? msg:'短信發(fā)送成功', ? ? ? ? ? ? ? ? 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:'參數(shù)錯誤' ? ? ? ? } ? ? ? }else{ ? ? ? ? //判斷驗證碼是否超時 ? ? ? ? var nowTime=await this.service.tools.getTime(); ? ? ? ? if((userTempResult[0].add_time-nowTime)/1000/60>30){ ? ? ? ? ? this.ctx.body={ ? ? ? ? ? ? success:false, ? ? ? ? ? ? msg:'驗證碼已經(jīng)過期' ? ? ? ? ? } ? ? ? ? }else{ ? ? ? ? ? //用戶表有沒有當(dāng)前這個手機號 ? ? ? ?手機號有沒有注冊 ? ? ? ? ? var userResult=await this.ctx.model.User.User.find({"phone":userTempResult[0].phone}); ? ? ? ? ? if(userResult.length>0){ ? ? ? ? ? ? this.ctx.body={ ? ? ? ? ? ? ? success:false, ? ? ? ? ? ? ? msg:'此用戶已經(jīng)存在' ? ? ? ? ? ? } ? ? ? ? ? }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{ ? ? ? //傳入?yún)?shù)正確 執(zhí)行增加操作 ? ? ? 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){ ? ? ? ? ? //跳轉(zhuǎn)到登入頁面 ? ? ? ? ? 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位數(shù)字*/ ? async getRandomNum(){ ? ? ? let num=''; ? ? ? for(var i=0;i<4;i++){ ? ? ? ? num+=Math.floor(Math.random()*10) ? ? ? } ? ? ? return num; ? ? } ? /*生成當(dāng)年當(dāng)月當(dāng)天的數(shù)字*/ ? async getDay(){ ? ? const day=sd.format(new Date(), 'YYYYMMDD'); ? ? return day; ? } ? /* 生成當(dāng)前時間*/ ? async getTime(){ ? ? ?var date=new Date(); ? ? ?return date.getTime(); ? } ? async md5(string){ ? /* 封裝一個md5加密*/ ? ? ? ? return ?md5(string); ? } ? async getFocusAddPath(filename){ ? ? ? /* ? ? ? ? ? 1: 獲取傳遞過來的圖片的名字, 獲取當(dāng)前日期 silly-datetime模塊 ? ? ? ? ? 2: 根據(jù)當(dāng)前的日期,設(shè)置對應(yīng)的文件夾,如果存在就不設(shè)置,不存在就設(shè)置 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(); ? /*毫秒數(shù)*/ ? ? ?/*圖片保存的路徑*/ ? ? ?let uploadDir=path.join(dir,d+path.extname(filename)); ? ? ?/*app\public\admin\upload\20190614\1560520826971.png */ ? ? return { ? ? ? uploadDir:uploadDir, ? ? ? /* 保存到數(shù)據(jù)庫的地址 */ ? ? ? 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
發(fā)送短信驗證碼
(需要上云片網(wǎng)購買短信服務(wù))
'use strict'; const Service = require('egg').Service; var https = require('https'); var qs = require('querystring'); class SendmsgService extends Service { ? async send(mobile,code) { ? ? //apikey自己到云片網(wǎng)上面去買。 ? ? var apikey = '092******************eec'; ? ? // 修改為您要發(fā)送的手機號碼,多個號碼用逗號隔開 ? ? var mobile = mobile; ? ? // 修改為您要發(fā)送的短信內(nèi)容 ? ? var text = '【java學(xué)習(xí)網(wǎng)】您的驗證碼是'+code; ? ? // 智能匹配模板發(fā)送https地址 ? ? var sms_host = 'sms.yunpian.com'; ? ? var send_sms_uri = '/v2/sms/single_send.json'; ? ? // 指定模板發(fā)送接口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, ? ? ? ? };//這是需要提交的數(shù)據(jù) ? ? ? ? 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;
到此這篇關(guān)于使用egg.js實現(xiàn)手機、驗證碼注冊的項目實踐的文章就介紹到這了,更多相關(guān)egg.js 手機驗證碼注冊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
cropper.js和exif.js實現(xiàn)頭像上傳縮放裁剪旋轉(zhuǎn)
這篇文章主要為大家詳細介紹了cropper.js和exif.js實現(xiàn)頭像上傳縮放裁剪旋轉(zhuǎn),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02JavaScript設(shè)計模式之模板方法模式原理與用法示例
這篇文章主要介紹了JavaScript設(shè)計模式之模板方法模式原理與用法,結(jié)合實例形式分析了JavaScript模板方法模式的概念、組成、定義、使用等相關(guān)操作技巧與注意事項,需要的朋友可以參考下2018-08-08javascript實現(xiàn)不同顏色Tab標簽切換效果
這篇文章主要為大家詳細介紹了javascript實現(xiàn)不同顏色Tab標簽切換效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-04-04javascript 10進制和62進制的相互轉(zhuǎn)換
本節(jié)主要介紹了javascript 10進制和62進制的相互轉(zhuǎn)換,需要的朋友可以參考下2014-07-07關(guān)于javaScript注冊click事件傳遞參數(shù)的不成功問題
在javaScript中給一個html元素注冊click事件處理函數(shù)時,比如給該處理函數(shù)傳3個參數(shù)。可是不管是使用下面那種方式都不能給事件處理函數(shù)傳遞參數(shù)2014-07-07利用js給datalist或select動態(tài)添加option選項的方法
下面小編就為大家分享一篇利用js給datalist或select動態(tài)添加option選項的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01詳解如何讓InstantClick兼容MathJax、百度統(tǒng)計等
本篇文章主要介紹了如何讓InstantClick兼容MathJax、百度統(tǒng)計等,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09