node系列之数据接口注册登陆接口的实现
1、使用express脚手架创建项目
2、了解项目的目录结构
3、准备数据库相关文件
4、编写注册接口
5、编写登陆接口
6、验证登陆实现
7、预告
1、使用express脚手架创建项目
// 安装脚手架,只需安装一次
npm i express-generator -g
// 创建express项目
express myapp --view=ejs
cd myapp
// 安装依赖
npm i 
// 安装需要使用的模块
// 数据库模块 用户唯一id模块 密码加密模块 token模块
npm i mongoose node-uuid bcryptjs jsonwebtoken -S
2、了解项目的目录结构
bin
www ------- 服务器启动
node_modules ------- 项目的依赖文件
public ------- 静态资源文件夹
images ------- 静态图片
javascripts ------- 静态的js文件
stylesheets ------- 静态的样式表文件
routes ------- 路由文件
index.js ------- 默认的路由
users.js ------- 用户相关的路由
views ------- 路由对应的页面
index.ejs ------- 默认的首页
error.ejs ------- 错误页面
app.js ------- 使用中间件,注册路由
package.json ------- 描述文件
3、准备数据库相关文件
大勋在node系列之数据库mongoose的封装中给大家介绍了如何封装mongoose,可以先行查看如何封装,封装的文件夹为sql,如果不想看的,可以直接通过网盘下载该文件夹
将该sql文件放置项目的跟目录下
- myapp
 
 - sql
 
 - collection
 
 users.js
 
 db.js
 
 index.js
 
 
 
 4、编写注册接口
 
 目标文件: myapp/routes/users.js
 
 
 
 实现思路:使用post提交数据的方式,先以手机号查询有没有该用户,如果有该用户,提示用户该账号已经注册过了;如果没有该用户,则可以完成注册,首先得将密码加密,加密完成后插入数据库
 
 
 
 代码实现:
 
 
 
 // 找到用户集合
 
 var User = require('./../sql/collection/users');
 
 // 找到数据库封装文件
 
 var sql = require('./../sql');
 
 // 状态码的封装
 
 var utils = require('./../utils')
 
 // 用户唯一标识的id
 
 var uuid = require('node-uuid');
 
 // 密码加密模块
 
 var bcrypt = require('bcryptjs');
 
 var salt = bcrypt.genSaltSync(10); // 加密级别
 
 
 
 // 实现注册接口 -- post提交方式
 
 router.post('/register', (req, res, next) => {
 
 // 1、先获取表单信息
 
 let { username, password, tel } = req.body;
 
 // 2、根据手机号查询 用户集合中是否有该用户,如果有,返回有该账户,如果没有注册继续
 
 sql.find(User, { tel }, { id: 0 }).then(data => {
 
 // 2.1 判断有没有该用户
 
 if (data.length === 0) {
 
 // 2.2 没有该用户----继续完成注册操作
 
 // 2.2.1 生成用户的id
 
 let userid = 'users' + uuid.v1();
 
 // 2.2.2 对密码加密
 
 password = bcrypt.hashSync(password, salt)
 
 // 2.2.3 插入数据库
 
 sql.insert(User, { userid, username, password, tel}).then(() => {
 
 res.send(utils.registersuccess)
 
 })
 
 } else {
 
 // 2.3 已有该用户
 
 res.send(utils.registered)
 
 }
 
 })
 
 })
 
 
 
 附 状态码封装模块 myapp/utils/index.js
 
 module.exports = {
 
 registered: {
 
 code: '10000',
 
 message: '该用户已注册,请直接登录'
 
 },
 
 registersuccess: {
 
 code: '10101',
 
 message: '注册成功'
 
 }
 
 }
 
 
 
 5、编写登陆接口
 
 目标文件 myapp/routes/users.js
 
 实现思路:根据手机号查询有没有该用户,如果没有,提示用户未注册,如果有该用户,使用bcryptjs模块验证密码的有效性,如果有效,生成token,返回给前端相应的token值。
 
 var jwt = require('jsonwebtoken');
 
 // 实现登陆功能
 
 router.post('/login', (req, res, next) => {
 
 // 1、获取表单信息
 
 let { tel, password } = req.body;
 
 // 2、依据手机号查询有没有该用户
 
 sql.find(User, { tel }, { _id: 0 }).then(data => {
 
 // 2.1 判断有么有该用户
 
 if (data.length === 0) {
 
 // 2.2 没有该用户
 
 res.send(utils.unregister)
 
 } else {
 
 // 2.3 有该用户,验证密码
 
 // 2.3.1 获取数据库中的密码
 
 let pwd = data[0].password;
 
 // 2.3.2 比较 输入的 密码和数据库中的密码
 
 var flag = bcrypt.compareSync(password, pwd) // 前为输入,后为数据库
 
 if (flag) {
 
 // 2.3.3 密码正确,生成token
 
 let userid = data[0].userid
 
 let username = data[0].username
 
 let token = jwt.sign({ userid, username }, 'daxunxun', {
 
 expiresIn: 606024// 授权时效24小时
 
 })
 
 res.send({
 
 code: '10010',
 
 message: '登陆成功',
 
 token: token
 
 })
 
 } else {
 
 // 2.3.4 密码错误
 
 res.send({
 
 code: '10100',
 
 message: '密码错误'
 
 })
 
 }
 
 }
 
 })
 
 })
 
 
 
 6、验证登陆实现
 
 目标文件: myapp/app.js
 
 实现思路:很多的数据请求都需要登陆之后才能获取到,在此统一封装验证登陆
 
 // 引入token模块
 
 var jwt = require('jsonwebtoken');
 
 // 全局的路由匹配
 
 app.use((req, res, next) => {
 
 // 排除登陆注册页面
 
 if (req.url !== '/users/login' && req.url !== '/users/register') {
 
 // 不同形式获取token值
 
 let token = req.headers.token || req.query.token || req.body.token;
 
 // 如果存在token ---- 验证
 
 if (token) {
 
 jwt.verify(token, 'daxunxun', function(err, decoded) {
 
 if (err) {
 
 res.send({
 
 code: '10119',
 
 message: '没有找到token.'
 
 });
 
 } else {
 
 req.decoded = decoded;
 
 console.log('验证成功', decoded);
 
 next()
 
 }
 
 })
 
 } else { // 不存在 - 告诉用户---意味着未登录
 
 res.send({
 
 code: '10119',
 
 message: '没有找到token.'
 
 });
 
 }
 
 } else {
 
 next()
 
 }
 
 })