实现需求
实现过程
客户端使用用户名和密码请求登录
服务端收到请求后验证是否登录成功
成功:返回一个token给客户端
失败:提示失败信息
客户端收到token后存储token(token采用jwt进行加密,而不是普通的base64)
每次发起请求时将token发给服务端
服务端接收到请求后,token的合法性
成功:返回客户端所需数据
失败:返回验证失败的信息
流程图解
实现流程 准备工作 安装
初始化项目
安装express
启动node服务_新建app.js文件 1 2 3 4 5 6 7 8 9 10 11 const express = require ('express' );const app = express ();app.listen (4000 , () => { console .log ('serve is running on port: 4000' ); })
app.listen参数
启动端口
连接MySQL 下面的过程都可以看文档:sequelize文档
安装Sequelize和MySql 1 2 npm i sequelize npm i mysql2
连接到数据库_database/init.js 要连接到数据库,必须创建一个 Sequelize 实例. 这可以通过将连接参数分别传递到 Sequelize 构造函数或通过传递一个连接 URI 来完成
1 2 3 4 5 6 7 8 const { Sequelize } = require ('sequelize' );const sequelize= new Sequelize ('数据库名称' , 'root' , '你的密码' , { host : 'localhost' , port : '3306' , dialect : 'mysql' })
测试连接 引入到app.js
1 require ('./database/init' )
你可以使用 .authenticate()
函数测试连接是否正常:
1 2 3 4 5 6 try { await sequelize.authenticate (); console .log ('Connection has been established successfully.' ); } catch (error) { console .error ('Unable to connect to the database:' , error); }
关闭连接 默认情况下,Sequelize
将保持连接打开状态,并对所有查询使用相同的连接. 如果你需要关闭连接,请调用 sequelize.close()
(这是异步的并返回一个 Promise).
完整代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const { Sequelize } = require ('sequelize' );const sequelize= new Sequelize ('test_login' , 'root' , 'yyy674531' , { host : 'localhost' , port : '3306' , dialect : 'mysql' }) try { sequelize.authenticate (); console .log ('Connection has been established successfully.' ); } catch (error) { console .error ('Unable to connect to the database:' , error); } module .exports = {Sequelize , sequelize};
同步表模型 创建模型实例_database/models/User.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 const { Op , Model , DataTypes } = require ('sequelize' );const { Sequelize , sequelize } = require ('../init.js' );const User = sequelize.define ('users_info' , { username : { type : DataTypes .STRING , allowNull : false , unique : true , }, password : { type : DataTypes .STRING , allowNull : false , } }); (async () => { await User .sync ().then (() => { console .log ('user表模型已经同步' ); }) })();
导出到app.js并启动
实现路由部署(准备) Express 教程 4:路由和控制器
路由部署_express.Router 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const express = require ('express' );const router = express.Router ();router.get ('/home' , (req, res ) => { res.send ({msg : 'Welcome!' }); }) module .exports = router;
引入使用 1 2 3 4 5 const router = require ('./router/user' );app.use (express.urlencoded ({extended : false })); app.use ('/user' , router);
postman测试
实现注册功能 路由部署 1 2 3 4 5 router.post ('/register' , async (req, res) => { const {username, password} = req.body ; console .log (username); })
可以看到控制台已经打印了~说明能够获取到username的信息
注册功能说明:
服务器获取到浏览器传过来的username
首先检验是否存在这个username,如果存在就返回“该用户已经存在,请直接登录”
如果不存在,再进行创建
去哪里检验——MySQL数据库里面
怎么创建——利用MySQL的create
接下来会详细说明
用户查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const bcryptjs = require ('bcryptjs' );router.post ('/register' , async (req, res) => { const {username, password} = req.body ; const model = await User .findOne ({where : {username : username}}); if (model) { return res.send ({msg : '该用户已经存在,请直接登录!' }) }else { const user = await User .create ({username, password :bcryptjs.hashSync (password, 5 )}); res.send ({msg : '注册成功!' }); } })
postman测试:创建成功~
查询数据库:创建成功~
当我再次用同样的username进行注册请求的时候,返回结果为:该用户已经存在,请直接登录!
注册功能验证成功~
实现登录功能
登录功能说明:
通过发送username和password进行登录
登录功能部署 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const bcryptjs = require ('bcryptjs' );router.post ('/login' , async (req, res) => { const {username, password} = req.body ; console .log (req.body ); const model = await User .findOne ({where : {username : username}}); console .log (model); if (!model) { return res.send ({msg : '该用户不存在,请先注册!' }) } else { const passwordValid = bcryptjs.compareSync (password, model.dataValues .password ); if (!passwordValid) { return res.send ({msg : '密码错误!' }) } else { res.send ({msg : '登录成功!' }) } } })
正确输入用户名和密码:
输入错误密码:
输入未注册用户名:
token生成及返回_jsonwebtoken jwt中文文档
1 jwt.sign (payload, secretOrPrivateKey, [options, callback]);
1 2 3 const token = jwt.sign ({username}, 'ccken' )res.send ({token})
实现权限校验
权限校验说明:
token包含在请求头里面,所以第一步我们要获取token
如果没有token说明前面没有登录过或者是登录已经失效,返回“请登录”
利用token 密钥 和 payload对token进行解析
对解析结果进行校验查询
如果查询结果为空,返回’请注册‘
如果不为空,则说明“权限校验成功!”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 router.post ('/auth' , async (req, res) => { const token = String (req.headers .authorization ).split (' ' ).pop (); if (!token) return res.send ({msg : '请登录!' }) const {username} = jwt.verify (token, 'ccken' ); const model = User .findOne ({where : {username : username}}); if (!model) { return res.send ({msg : '请注册!' }); } else { res.send ({msg : '权限校验成功!' }) } })
代码 以上过程的代码放在github了~
参考 app.listen参数
sequelize文档
Express 教程 4:路由和控制器
jwt中文文档
cookie、session、token、jwt、单点登录