手机号注册、验证码校验
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;