node后台登录和注册
- 创建数据表(Users)
sequelize model:generate --name User --attributes username:string,password:string,openid:string,admin:boolean
sequelize db:migrate #运行迁移 - 创建一个 users.js的 文件
- 下载jsonwebtoken: jwt(json web token)网络通行令牌,有了这个令牌,能够在Restful风格的代码中识别用户信息
https://www.npmjs.com/package/jsonwebtoken
cnpm install jsonwebtoken –S - 在 users.js里引入 var jwt = require('jsonwebtoken');并且配置登录(未完善)的接口代码:
- 在数据库 添加一个 用户:
然后测试一个 登录接口:
此时登录密码,在数据库是明文, 所以还不完善;只是作为测试登录 - 配置 app.js ,在app.js中加上中间件, 只要 请求头里 携带 token 才能访问页面:(node的导航守卫,配置没带token就不能访问页面)
- 测试:
没有带请求头 token 访问接口
带有请求头 token 访问接口
请求头 带上 错误的 token
- 解析当前加密的信息:
res.json(decoded) 可以返回当前解密后的 信息
var express = require('express'); var router = express.Router(); var models = require('../../models') var jwt = require('jsonwebtoken');// 加密 router.post('/login', function(req, res, next) { var username = req.body.username var password = req.body.password if(!username || !password){ res.json({success:false,message:'用户名或密码错误'}) return; } models.User.findOne({ where:{ username:username, password:password } }).then(user=>{ if(!user){ res.json({success:false,message:'用户名或者密码错误!'}) } // 使用jwt 加密当前的用户输入的信息,并且秘钥加 盐 var token = jwt.sign({user:user},'0429'); res.json({ success:true, message:'请求成功', token:token }) }) }); module.exports = router;
app.use(function(req, res, next) { // 6.不需要验证就可以访问的页面(注册页面,登录页面) var allowUrl = ['/admin/users/login','/admiin/users/register','/users/login'] if(allowUrl.indexOf(req.url) != '-1') return next()// 如果访问的页面在allowUrl数组里,就允许访问 // 1.验证token是否存在 var token; // 如果用户请求头携带了token 并且 token前面 带有 Bearer if(req.headers.authorization && req.headers.authorization.split(' ')[0]==='Bearer'){ token = req.headers.authorization.split(' ')[1] }else if(req.query.token){ token = req.query.token; } // 2.如果token不存在, if(!token){ return res.status(401).send({ success:false, message:'当前接口需要认证才能访问' }) } // 3.先解密token,然后判断token是否正确; // verify解密 decoded是解密后的信息(也就是被加密的信息) jwt.verify(token,'0429',function(err,decoded){ if(err){ return res.status(401).send({ suceess:false, messag:'token过期,请重新登录' }) } // res.json(decoded) 返回解密后的信息 // 4.验证是否是后台管理员 var reg = /\admin/ if(reg.test(req.url) && !decoded.user.admin){ return res.status(401).send({ success:false, message:"当前接口是管理员接口" }) } //5. 解析出来的数据存入req req.decoed = decoded; next()// next() 功能就是 运行下一个函数 }) });
注册:
- 由于目前密码在数据表中存的是明文的,不安全,所以在用户注册的时候就需要对密码进行加密处理
https://www.npmjs.com/package/bcryptjs
cnpm install bcryptjs –S 安装加密包 - 在 users.js的 文件 引入包:
- 并且配置登录的接口代码:
- 测试:
成功注册
- 但是有一个问题存在 , 由于注册的时候把密码 加密 存到了数据库
如果用户登录 就会登录不上, 因为 此时的密码已经被 加密存在数据库了
- 用户登录的时候 , 通过解密对比 用户输入的 和 数据库被加密的 是否一致
此时就要修改一下 登录的代码:完善登录代码:
- 动态的 控制 盐:
7.1 npm install dotenv -S
Dotenv是一个零依赖模块,可将环境变量从.env文件加载到process.env中
7.2 在项目根目录: 创建一个 .env的文件, 并且配置如下代码:
SECRET=0429 // SECRET:后面是你要设置的 盐
7.3 打开users.js文件 和 app.js文件, 分别引入:
require("dotenv").config();
然后把两个文件需要用到 盐 的地方改成:
process.env.SECRET
var bcrypt = require('bcryptjs');// 加密
// users.js var bcrypt = require('bcryptjs');// 加密 // 注册 router.post('/register',function(req,res,next){ var username = req.body.username var password = req.body.password var check_password = req.body.check_password // 1.判断用户名密码是否为空 if(!req.body.username || !req.body.password){ res.json({succes:false,message:'用户名或密码必填'}) return } // 2.判断两次密码是不是一致 if(check_password != password){ res.json({success:false,message:'两次输入的密码不一致'}) } // 3.查找用户名是否被注册 models.User.findOne({ where:{ username:username } }).then(user=>{ if(user){// 已存在用户名 res.json({success:false,message:'用户名已注册'}) return } // 用户名不存在, 就在数据库添加这个注册信息 password = bcrypt.hashSync(password,8)// 加密当前注册的密码,并且进行重新赋值 models.User.create({ username:username, password:password,// 此时的password已经被加密过 admin:true }).then((user)=>{ res.json({ success:true, message:'请求成功', user:user }) }) }) })
// 登录 router.post('/login', function(req, res, next) { var username = req.body.username var password = req.body.password if(!username || !password){ res.json({success:false,message:'用户名或密码错误'}) return; } models.User.findOne({ where:{ username:username, } }).then((user)=>{ if(!user) return res.json({success:false,message:'用户名不存在'}) // 如果用户输入的密码和数据库加密的一致,就返回true if(!bcrypt.compareSync(password,user.password)){ res.json({success:false,message:'密码错误!'}) return; } // 使用jwt 加密当前的用户输入的信息,并且秘钥加 盐 var token = jwt.sign({ user:{ username:username, admin:true // 返回为管理员用户 } },process.env.SECRET,{expiresIn:60 * 60 * 24 * 7 }); res.json({ success:true, message:'登陆成功', token:token }) }) });