V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wangweifeng
V2EX  ›  Node.js

邮箱注册,激活,登陆相关案例

  •  
  •   wangweifeng · 2017-09-29 11:28:05 +08:00 · 3446 次点击
    这是一个创建于 2372 天前的主题,其中的信息可能已经有所发展或是发生改变。

    email-verify

    具体的详细代码 github 现在的登陆系统除了第三方登陆接入以外,主要有短信登陆和邮箱登陆,按照现在实名制的特点,现在的短信登陆比较多,但是还是有一些会用到邮箱登陆的。 本文主要是关于邮箱登陆的相关案例,通俗的说就是用户使用邮箱注册,当注册成功时,会给注册用户发邮件进行激活,当然这个邮件有一定的时效性。当用户激活后可以正常使用相关的功能,没激活,当登陆时会提示没激活,是否需要在发送一条邮件激活。

    1. 使用工具

    • node v8.5.0
    • mongodb
    • ioredis
    • postman

    2. 项目结构

    项目结构图

    图中说明了关键文件的含义

    3. 用户注册接口

    当用户注册时,首先检查必要字段是否传入以及邮箱密码是否符合规范,然后检查邮箱是否已注册,当注册成功时会发送一个邮件给用户用来激活这个账号,这个发送的邮件内容为一个链接,包含了这个用户的邮箱以及 code,code 使用 reids 设置了过期时间。(未激活时用户状态为 0,激活状态为 1 ) 路由 routes 中注册路由如下:

     //user_regist
    router.post('/user_regist', userCtrl.user_regist);
    

    controllers 中注册的部分代码如下:

     	try {
    		const user = await findUserAsyc({ 'useremail': user_email });//验证用户是否已注册
    		if (user) {
    			respondData.status = 10002;
    			respondData.error = "邮箱已注册";
    			return res.json(respondData);
    		}
    		//用户参数
    		const userpassword = md5(user_password);
    		const userInfo = {
    			useremail: user_email,
    			username: user_name,
    			userpwd: userpassword,
    			status: 0,
    			create_time: Date.now('YYYY-MM-DD')
    		};
    		//新建用户
    		console.log("newGuess.save userInfo-->" + JSON.stringify(userInfo));
    		const newUser = new UserModel(userInfo);
    		newUser.save(function (err, data) {
    			if (err) {
    				console.log("newGuess.save err-->" + JSON.stringify(err));
    				respondData.status = "00001";
    				respondData.error = "mongodb system error";
    				return res.json(respondData);
    			}
    			console.log("newGuess.save data -->" + JSON.stringify(data));
    			let userEmail = data.useremail;
    			let sendEmail = sendUserEmail(userEmail);
    			console.log("sendEmail:" + sendEmail);
    			respondData.msg = "新用户注册成功 and 激活邮箱发送成功";
    			return res.json(respondData);
    		});
    	} catch (error) {
    		//错误处理
    		console.log("controllers/UserController.js/user_regist error -->" + JSON.stringify(error));
    		respondData.error = error;
    		return res.json(respondData);
    	}
    
    

    邮箱发送部分代码

    	var config_email = {
    		host: 'smtp.163.com',
    		post: 25, // SMTP 端口
    		//secureConnection: true, // 使用 SSL
    		auth: {
    			user: '[email protected]',
    			//这里密码不是 qq 密码,是你设置的 smtp 密码
    			pass: 'wwf'
    		}
    	};
    	var transporter = nodemailer.createTransport(config_email);
    
    	var html = "<div>http://127.0.0.1:3000?code=" + code + "&account=" + cnd + "</div>";
    	console.log(html);
    	var data = {
    		from: '[email protected]', // 发件地址
    		to: cnd, // 收件列表
    		subject: 'Hello feng', // 标题
    
    		//text: html // 标题 //text 和 html 两者只支持一种
    		html: html // html 内容
    	};
    	console.log(data);
    	transporter.sendMail(data, function (err, info) {
    		if (err) {
    			return (err);
    		}
    		console.log(info.response);
    		return (info.response);
    
    	});
    

    使用 postman 模拟注册 postman 模拟注册

    此时的截图正好把发送邮箱的消息也截取了,完美

    用户没有激活时数据库中这条用户的 status=0 ;如图: 数据库用户信息 数据库用户信息

    4. 用户邮箱激活

    通过点击邮箱中的链接会激活邮箱,当邮箱和 code 不匹配时,会返回邮箱不匹配消息,当 code 过期时,会返回 code 过期消息,当用户已激活时,会告诉已激活,不要重复激活,当用户信息无上述的几种情况时会,提示激活成功。 路由 routes 中激活路由如下:

    //user_activation
    router.get('/user_activation', userCtrl.user_activation);
    

    controllers 中注册的部分代码如下:

    	try {
    		let codeVal = await Jtoken(code);
    		if (!codeVal) {
    			respondData.error = "code 失效,请重新发送邮件激活";
    			return res.json(respondData);
    		}
    		let userinfo = JSON.parse(codeVal);
    		if (userinfo.userEmail !== user_email) {
    			respondData.error = "邮箱不正确";
    			return res.json(respondData);
    		}
    		const user = await findUserAsyc({ 'useremail': user_email });//验证用户是否已注册
    		if (user) {
    			if (user.status === 0) {
    				UserModel.update({ 'useremail': user_email }, { '$set': { status: 1 } }, function (err, results) {
    					if (err) {
    						console.log("UserModel.update err-->" + JSON.stringify(err));
    						respondData.status = "00001";
    						respondData.error = "mongodb system error";
    						return res.json(respondData);
    					}
    					respondData.msg = "邮箱激活成功";
    					return res.json(respondData);
    				})
    			} else if (user.status === 1) {
    				respondData.msg = "此邮箱已经激活了哦,不要重复激活";
    				return res.json(respondData);
    			}
    		}
    	} catch (error) {
    		//错误处理
    		console.log("controllers/UserController.js/user_regist error -->" + JSON.stringify(error));
    		respondData.error = error;
    		return res.json(respondData);
    	}
    

    使用 postman 模拟激活成功 postman 模拟激活成功 使用 postman 模拟激活 code 失效 postman 模拟激活 code 失效 激活成功时数据库的用户信息 激活成功时数据库的用户信息

    5. 用户登陆接口

    当用户未激活时,登陆会告知未激活,需要去激活,当已激活时信息正常时会成功登陆,当成功登陆时会返回用户的一些信息以及加一个 token。 路由 routes 中登陆路由如下:

    //user_login
    router.post('/user_login', userCtrl.user_login);
    

    controllers 中登陆的部分代码如下:

    	try {
    		const user = await findUserAsyc({ 'useremail': user_email });//验证用户是否已注册
    		if (!user) {
    			respondData.status = 10000;
    			respondData.error = "邮箱未注册";
    			return res.json(respondData);
    		}
    		const userverify = await findUserVerify(user_email,user_password);//验证用户
    		if(!userverify){
    			respondData.status = 10005;
    			respondData.error = "邮箱或密码错误";
    			return res.json(respondData);
    		}
    		console.log(userverify);
    		if(userverify.status === 0){
    			respondData.status = 10006;
    			respondData.error = "邮箱未激活,请激活邮箱";
    			return res.json(respondData);
    		} else if(userverify.status === 1){
    			const tokenexpiraton = 1800;
    			const token = require('crypto').randomBytes(16).toString('hex');
    			const tokenContent = {
    				useremail: userverify.useremail,
    				username: userverify.username
    			};
    			redis.set(token, JSON.stringify(tokenContent));
    			redis.expire(token, tokenexpiraton);
    			const userBackInfo = {};
    			userBackInfo.token = token;
    			userBackInfo.useremail = userverify.useremail;
    			userBackInfo.username = userverify.username;
    			userBackInfo._id = userverify._id;
    			respondData.data.push(userBackInfo);
    			respondData.msg = "登陆成功";
    			return res.json(respondData);
    		}	
    	} catch (error) {
    		//错误处理
    		console.log("controllers/UserController.js/user_regist error -->" + JSON.stringify(error));
    		respondData.error = error;
    		return res.json(respondDaata);
    	}
    

    未激活登陆时 未激活登陆时 已激活登陆时 已激活登陆时

    6. 后续

    目前来说只有注册,激活,登陆接口,后续也可以实现更多的功能,同时还没有测试,其实也可以加上测试的。

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3247 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 11:46 · PVG 19:46 · LAX 04:46 · JFK 07:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.