koa2+mysql+vue实现用户注册、登录、token验证
说明:
node.js提供接口,vue展现页面,前后端分离,出于编辑器功能和编辑习惯,vue用HbuilderX,node.js用VScode。(PS:仅作为学习笔记,如有不当之处欢迎指出,在此先谢为敬~~~)
环境:
首先需要有node.js环境,安装教程 在这里,最好下载较新的版本,对es6、es7有更好的支持,再装个 淘宝镜像,完毕!
后台:
1、安装mysql
1.1、mysql下载地址
解压到安装位置,修改环境变量,win10编辑环境变量很方便了,win7的话记得以 ; 分割开

1.2、添加配置文件
在mysql的bin目录下,新建my.ini文件(如果没有),打开my.ini文件,写入以下配置内容
[mysqld]
# 设置3306端口
port=3306
# 设置mysql的安装目录
basedir=D:\\myInstalls\\mysql-8.0.11
# 设置mysql数据库的数据的存放目录
datadir=D:\\myInstalls\\mysql-8.0.11\\Data
# 允许最大连接数
max_connections=200
# 允许连接失败的次数。这是为了防止有人从该主机试图攻击数据库系统
max_connect_errors=10
# 服务端使用的字符集默认为UTF8
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 默认使用“mysql_native_password”插件认证
default_authentication_plugin=mysql_native_password
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[client]
# 设置mysql客户端连接服务端时默认使用的端口
port=3306
default-character-set=utf8
1.3、安装
以管理员身份运行cmd,进入mysql的bin目录下,不进入也行,因为我们已经配置了环境变量
初始化数据库,运行 mysqld --initialize --console,记住红色框内的初始密码

安装mysql服务,运行 mysqld --install [服务名] ,服务名可以不写,安装完毕 net start mysql 启动mysql

启动成果,mysql停止指令 net stop mysql
默认密码太复杂,改个简单的,首先运行 mysql -u root -p 进入mysql,密码是刚才记住的初始密码

修改密码指令:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';

OK,mysql我们已经有了,接下来搭建koa2!
2、搭建koa2项目
(你可以使用系统自带的cmd窗口,也可以用编辑器自带的。我这里用VScode的命令行终端,看起来特别虚浮~~~)
2.1、我们不一步步搭建,采用koa2框架,并使用koa-generator生成项目,类似vue-cli
安装指令:cnpm install koa-generator -g

2.2、在你的项目目录下,运行 koa2 项目名,生成项目,如:koa2 paopao(泡泡是我的猫的名字~~~)

成功,根据上面提示走~~~
cd paopao 进入项目目录
cnpm install 安装项目依赖
cnpm start paopao 运行项目(cnpm是淘宝镜像)
有个报错大概意思是这个包不再维护了,cnpm uninstall koa-onerror 卸载,重新装最新的版本 cnpm install koa-onerror --save

在浏览器输入:localhost:3000,浏览器运行结果(左),项目结构(右)

3、实现API
3.1、用sequelize来操作数据库,同时安装mysql、mysql2
cnpm install sequelize mysql mysql2 --save

所有安装的依赖可以在package.json里查看:

注意:我在使用时发现koa-static(处理静态文件的中间件),默认3.0.0版本会报错,于是更新成了最新版本
使用cnpm install koa-static@5.0.0 --save更新,再查看package.json,版本变成了5.0.0即可
3.2、连接数据库
在项目根目录下建一个config文件夹,在该文件夹建一个js文件,取名db.js,用来配置数据库连接
config-->db.js
var Sequelize = require("sequelize")
var sequelize = new Sequelize('paopao','root','happy',{
host:'localhost',
dialect:'mysql',
operatorsAliases:false,
dialectOptions:{
//字符集
charset:'utf8mb4',
collate:'utf8mb4_unicode_ci',
supportBigNumbers: true,
bigNumberStrings: true
},
pool:{
max: 5,
min: 0,
acquire: 30000,
idle: 10000
},
timezone: '+08:00' //东八时区
});
module.exports = {
sequelize
};
paopao是我的数据库表名,root数据库用户名,happy数据库用户密码
3.3、定义数据库模型
在根目录建一个module文件夹,在module文件下面建一个user.js,用来定义数据模型,告诉sequelize怎么跟数据库的数据一一对应
module-->user.js
module.exports = function(sequelize,DataTypes){
return sequelize.define(
'user',
{
userId:{
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: true,
autoIncrement: true
},
mobileNo:{
type: DataTypes.STRING,
allowNull: false,
field: 'mobileNo'
},
password:{
type: DataTypes.STRING,
allowNull: false,
field: 'password'
}
},
{
timestamps: false
}
);
}
3.4、数据库操作和功能处理
controller-->user.js 添加以下代码
//引入db配置
const db = require('../config/db') //引入sequelize对象
const Sequelize = db.sequelize //引入数据表模型
const user = Sequelize.import('../module/user')
//自动创建表
user.sync({ force: false }); //数据库操作类
class userModule {
static async userRegist(data) {
return await user.create({
password: data.password,
mobileNo: data.mobileNo
})
} static async getUserInfo(mobileNo) {
return await user.findOne({
where: {
mobileNo
}
})
}
}
数据库操作有了,接下来进行功能处理,还是在该文件添加
controller-->user.js 里添加该userController 类,并将之exports出去
//功能处理
class userController { } module.exports = userController;
用户注册:
在 userController 类里添加用户注册逻辑
//注册用户
static async create(ctx) {
const req = ctx.request.body;
if (req.mobileNo && req.password) {
try {
const query = await userModule.getUserInfo(req.mobileNo);
if (query) {
ctx.response.status = 200;
ctx.body = {
code: -1,
desc: '用户已存在'
}
} else {
const param = {
password: req.password,
mobileNo: req.mobileNo,
userName: req.mobileNo
}
const data = await userModule.userRegist(param); ctx.response.status = 200;
ctx.body = {
code: 0,
desc: '用户注册成功',
userInfo: {
mobileNo: req.mobileNo
}
}
} } catch (error) {
ctx.response.status = 416;
ctx.body = {
code: -1,
desc: '参数不齐全'
}
}
}
}
因为还要做登录超时token验证,用户登录成功还要返回token,为了生成token,我们需要安装几个中间件
cnpm install jsonwebtoken --save 导入jwt模块
cnpm install koa-jwt --save koa提供的jwt中间件
在app.js里添加如下代码:
unless()表示里面的regist、login不做token验证
const koajwt = require('koa-jwt')
// logger
app.use(async (ctx, next) => {
return next().catch((err) => {
if(err.status === 401){
ctx.status = 401;
ctx.body = {
code: '-2000',
desc: '登陆过期,请重新登陆'
};
}else{
throw err;
}
})
})
app.use(koajwt({
secret: '123456'
}).unless({
path: [/^\/user\/regist/,/^\/user\/login/]
}))
为了解析token,在public目录下新建tool.js,加入解析token的代码
const getToken = require('jsonwebtoken')
exports.verToken = function(token){
return new Promise((resolve,rejece) => {
const info = getToken.verify(token.split(' ')[1],"123456");
resolve(info);
})
}
返回controller-->user.js,添加
//引入jwt做token验证
const jwt = require('jsonwebtoken') //解析token
const tools = require('../public/tool') //统一设置token有效时间 为了方便观察,设为10s
const expireTime = '10s'
用户登录:
之后就可以写用户登录逻辑了
controller-->user.js-->userController 类里添加
通过 jwt.asign() 方法生成token,这里的123456跟app.js里的123456相同,就理解为一个秘钥吧~~
//密码登陆
static async login(ctx) {
const req = ctx.request.body;
if (!req.mobileNo || !req.password) {
return ctx.body = {
code: '-1',
msg: '用户名或密码不能为空'
}
} else {
const data = await userModule.getUserInfo(req.mobileNo);
if (data) {
if (data.password === req.passWord) {
//生成token,验证登录有效期
const token = jwt.sign({
user: req.mobileNo,
passWord: req.password
}, '123456', { expiresIn: expireTime });
const info = {
createdAt: data.createdAt,
updatedAt: data.updatedAt,
mobileNo: data.mobileNo,
userId: data.userId
}
return ctx.body = {
code: '0',
token: token,
userInfo: JSON.stringify(info),
desc: '登陆成功'
}
} else {
return ctx.body = {
code: '-1',
desc: '用户密码错误'
}
}
} else {
return ctx.body = {
code: '-1',
desc: '该用户尚未注册'
}
}
};
}
为了验证token是否过期,我们再定义一个获取用户信息的逻辑,登陆10s后获取用户信息,验证token是否过期
获取用户信息:
controller-->user.js-->userController 类里添加
//获取用户信息(除密码外)
static async getUserInfo(ctx){
const req = ctx.request.body;
const token = ctx.headers.authorization;
if(token){
try {
const result = await tools.verToken(token);
if (!req.mobileNo) {
return ctx.body = {
code: '-1',
desc: '参数错误'
}
} else {
let data = await userModule.getUserInfo(req.mobileNo);
if (req.mobileNo == data.mobileNo) {
const info = {
createdAt: data.createdAt,
updatedAt: data.updatedAt,
mobileNo: data.mobileNo,
userId: data.userId
};
return ctx.body = {
code: '0',
userInfo: JSON.stringify(info),
desc: '获取用户信息成功'
}
}
}
} catch (error) {
ctx.status = 401;
return ctx.body = {
code: '-1',
desc: '登陆过期,请重新登陆'
}
}
}else{
ctx.status = 401;
return ctx.body = {
code: '-1',
desc: '登陆过期,请重新登陆'
}
}
}
3.5、路由,即处理请求的url,使用koa-router
不用重新导入,koa-generator已经帮我们导入了,直接使用
在routes目录下新建文件 user.js
写入以下代码:
routes-->user.js
const Router = require('koa-router');
const userController = require('../controller/user')
const router = new Router({
prefix: '/user'
});
//用户注册
router.post('/regist',userController.create)
//密码登陆
router.post('/login',userController.login)
//获取用户信息
router.post('/getUserInfo',userController.getUserInfo)
module.exports = router;
然后在入口文件app.js引入

使用

完成这些以后,cnpm run dev 启动项目(依赖nodemon,package.json里面有,这样每次更改代码以后不用手动重新启动)
启动正常如下:

如果有报错,提示缺少这包那包的,不用着急!
把根目录下的node_modules目录删除
检查一遍package.json
确认无误后重新cnpm install
再次启动 cnpm run dev ~~~
补充一点,如果想在其他端口启动,在app.js里添加 app.listen(3333),修改为3333端口,自动热刷新~~~蛋是此时接口仍然不可调试,因为存在跨域问题

3.6、解决跨域,koa-cors
koa同样提供了解决跨域的依赖包
cnpm install koa-cors --save
在app.js添加:

现在可以测试接口了,随便写个ajax或者使用postman,postman测试结果:
注册:


登录:

查看数据库结果(使用的是破解版Navicat图形化数据库管理工具):

到此为止,API就完成了,最后一步,验证token过期有没有效果
4、结合VUE验证token
写到太晚了,想起来今天还没给泡泡铲屎,VUE就不写那么详细了,有空再补上 ~.~
我就贴一下代码和验证结果
vue项目里,在接口文件里:
import axios from 'axios';
import qs from 'qs';
import route from '../router';
import {
message
} from 'ant-design-vue' axios.interceptors.request.use(function(config) {
// 处理请求参数
config.data = qs.stringify(config.data) //将token写入请求头
if (window.localStorage.getItem('token')) {
config.headers.Authorization = `Bearer ${window.localStorage.getItem('token')}`;
} return config;
}, function(error) {
// 对请求错误做些什么
return Promise.reject(error);
}); axios.interceptors.response.use(
response => {
return response
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
message.error("登录过期,请重新登录!", ()=>{
window.localStorage.removeItem("token"); //可能是token过期,清除它
route.replace({ //跳转到登录页面
path: '/login',
query: {
// 将跳转的路由path作为参数,登录成功后跳转到该路由
redirect: route.currentRoute.fullPath
}
});
})
}
}
return Promise.reject(error) // 返回接口返回的错误信息
}
); //注册
export const regist = params => {
return axios.post('http://localhost:3333/user/regist', params, {}).then(res => res.data)
} //登录
export const login = params => {
return axios.post('http://localhost:3333/user/login', params, {}).then(res => res.data)
} //获取用户信息
export const getUserInfo = params => {
return axios.post('http://localhost:3333/user/getUserInfo', params, {}).then(res => res.data)
}
axios.interceptors.request.use拦截请求,给请求头加上token
axios.interceptors.response.use拦截响应,如果返回401,token过期,跳回login路由
登录后10s再请求用户数据,返回登录过期:

总结:完结撒花,如有不当指出,欢迎各位大神指出,我该铲屎去了 ~.~
koa2+mysql+vue实现用户注册、登录、token验证的更多相关文章
- 全栈前端入门必看 koa2+mysql+vue+vant 构建简单版移动端博客
koa2+mysql+vue+vant 构建简单版移动端博客 具体内容展示 开始正文 github地址 <br/> 觉得对你有帮助的话,可以star一下^_^必须安装:<br/> ...
- 分享Node.js + Koa2 + MySQL + Vue.js 实战开发一套完整个人博客项目网站
这是个什么的项目? 使用 Node.js + Koa2 + MySQL + Vue.js 实战开发一套完整个人博客项目网站. 博客线上地址:www.boblog.com Github地址:https: ...
- Koa2+MySQL+VUE+ElementIUI搭建简单的后台管理小系统
如题,前端入坑许久,还是写个小东西出来吧 想要搭建自己的一个后台管理,实现简单的增删改查,看起来很简单 其实是真的简单,没有想的那么难,我也就写了一个月吧, 当然是假的,其实也就每天一两个小时,花了大 ...
- koa2+redis+jwt token验证,简单注册登录
首先新建文件夹命名koa-server,npm init,相关包的安装就不说了,这是我的package.json 新建index.js文件,编码如下,config全局配置不用管,redis是一个简单的 ...
- vue axios封装以及登录token过期跳转问题
Axios配置JWT/封装插件/发送表单数据 首先请务必已仔细阅读 Axios 文档并熟悉 JWT: 中文文档 JWT 中文文档 安装 npm install axios npm install es ...
- koa2,koa-jwt中token验证实战详解
用户身份验证通常有两种方式,一种是基于cookie的认证方式,另一种是基于token的认证方式.当前常见的无疑是基于token的认证方式.以下所提到的koa均为koa2版本. token认证的优点是无 ...
- nodeJS---express4+passport实现用户注册登录验证
网上有很多关于passport模块使用方法的介绍,不过基本上都是基于express3的,本文介绍在express4框架中使用passport模块. 前言 passport是一个功能单一,但非常强大的一 ...
- express框架+jade+bootstrap+mysql开发用户注册登录项目
完整的项目代码(github):https://github.com/suqinhui/express-demo express是基于Node.js平台的web应用开发框架,用express框架开发w ...
- Ionic3的http请求如何实现token验证,并且超时返回登录页
要求 后台提供的接口,不能让人随便输入个链接就能访问,而是要加入一个token,token是动态的,每次访问的时候判断,有权限并且未过期的时候才可以访问接口. 后台的设计是 在登录的时候,首先要pos ...
随机推荐
- DFS(三):八皇后问题
[例1]八皇后问题. 在一个8×8国际象棋盘上,放置8个皇后,每个皇后占一格,要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行.同一列或同一对角线上.问共有多少种不同的放置方法? (1 ...
- JQuery插件 aos.js-添加动画效果
原文地址:http://www.mamicode.com/info-detail-1785357.html 简介: aos.js是一款效果超赞的页面滚动元素动画jQuery动画库插件.该动画库可以在页 ...
- 【shell脚本】检测当前用户是否为超级管理员===checkRoot.sh
检测当前用户是否为超级管理员,是则使用yum安装vsftpd,不是则输出提示信息 脚本赋予执行权限 [root@VM_0_10_centos shellScript]# chmod a+x check ...
- CompletableFuture1
public class CompletableFutureTest { public static void main(String[] args) throws Exception { test5 ...
- IIS锁定是默认设置的 (overrideModeDefault="Deny")问题解决
发布网站时提示错误 锁定是默认设置的 (overrideModeDefault="Deny"),或者是通过包含 overrideMode="Deny" 或旧有的 ...
- .net core EF Core 调用存储过程
在这里,我们将尝试去学习一下 .net core EF Core 中调用存储过程. 我们知道,EF Core 是不支持直接调用存储过程的,那它又提供了什么样的方式去执行存储过程呢?有如下方法: 1.F ...
- git 创建标签 tag
1. git tag <name>就可以打一个新标签 加上-a参数来创建一个带备注的tag,备注信息由-m指定.如果你未传入-m则创建过程系统会自动为你打开编辑器让你填写备注信息. git ...
- linux中查找包含指定内容的文件
Linux查找文件内容的常用方法 ##文件名+内容 grep -r "查询内容" 文件目录 ##只显示包含内容的文件名 grep -r -l "查询内容" 文件 ...
- Win10 手动安装 WSL 并修改默认登录用户为 root
首先要在"程序和功能"里面开启这个服务 然后重启系统使其生效. 然后打开 PowerShell,输入: Invoke-WebRequest -Uri https://aka.ms/ ...
- Git以及GitHub的一些基本使用
1:注册GitHub账号: https://github.com/ 2:Git bash工具下载地址 https://gitforwindows.org/ 3:怎么在GitHub 新增 SSH Key ...