1、Vue2
vue2主要功能包括登入、退出、用户权限、表格的增删改查、文件下载。
Vue2项目地址https://gitee.com/www6/finance1.git
2、node.js编写后端接口
2.1、项目初始化
后端地址https://gitee.com/www6/finance-backend.git
创建项目
npm install -g koa-generator //安装koa-generator
koa2 创建项目名
在utils/index.js封装token
var jwt = require('jsonwebtoken');
const { secret, tokenExpires } = require('../conf');
exports.createToken = (user) => {
return jwt.sign(user, secret, {
expiresIn: tokenExpires,
});
};
exports.vertifyToken = (token) => {
try {
var decoed = jwt.verify(token, secret);
} catch (e) {
} finally {
return decoed;
}
};
exports.getUser = (token) => {
return jwt.decode(token, secret);
};
响应处理
// 响应处理 app.js
app.context.success = function (data) {
this.body = {
code: 20000,
data,
};
};
app.context.faild = function (data) {
this.body = {
code: 102,
data,
};
};
app.context.tokenExpires = function (data) {
this.body = {
code: 603,
data,
};
};
创建成功之后,接着下一步。
2.2、建立Mysql链接
根目录新建models/db.js文件
var mysql = require('mysql');
const { db } = require('../conf');
var pool = mysql.createPool(db);
exports.query = function(sql,params=[]) {
if (!params) {
console.log('当前查询参数没有值,请查看',params);
}
return new Promise((resolve,reject)=>{
pool.getConnection(function (err, connection) {
if (err) throw err; // not connected!
// Use the connection
connection.query(sql,params, function (error, results, fields) {
// 调试log
console.log(`${sql}==>${params}=数据=>${results}`);
connection.release();
// Handle error after the release.
if (error) {
console.log('db出现异常:',error)
return reject(error)
}
resolve(results);
// Don't use the connection here, it has been returned to the pool.
});
});
});
}
根目录下新建conf.js文件
exports.db = {
connectionLimit: 10,
host: "localhost",
user: "xxx",
password: "xxx",
database: "xxx",
};
exports.secret = "xxx";
exports.tokenExpires = 6000 * 3;
exports.whiteList = ["/user/login", "/user/logout"];
2.3、登入
新建routes/user.js文件
const router = require('koa-router')()
const { doLogin} = require('../controllers/user');
router.prefix('/user')
.post('/login',doLogin)
module.exports = router
新建controllers/user.js文件
const {findUserByAccount} = require('../models/user');
const { createToken, vertifyToken, getUser } = require('../utils');
exports.doLogin = async (ctx, next) => {
let { account, password } = ctx.request.body;
if (!account || !password) {
return ctx.faild('必须传递用户名和密码');
}
const res = await findUserByAccount(account);
if (res.length === 0) {
return ctx.faild('用户名或者密码不存在');
}
let user = res[0];
if (user.password != password) {
return ctx.faild('用户名或者密码不存在');
}
const saveUser = {
id: user.id,
account: user.account,
// 权限
type: user.role_id,
};
// 生成token
const token = createToken(saveUser);
ctx.success({
token,
});
};
;
新建models/user.js文件
const { query } = require('../models/db');
exports.findUserByAccount = account => query('select * from user where account = ?',[account]);
2.4、中间件处理
const { whiteList } = require('../conf');
const { vertifyToken, getUser } = require('../utils');
exports.checkLogin = async (ctx, next) => {
// 非登录、退出
// 需要检查的
if (!whiteList.includes(ctx.url)) {
const { token } = ctx.headers;
let tokenIndex = ctx.blackTokenList.indexOf(token);
// 验证token
if (!vertifyToken(token)) {
// 弹出这个元素,不允许访问,重新获取token
ctx.blackTokenList.splice(tokenIndex, 1);
return ctx.tokenExpires('无效token,请登录再试!');
} else {
// 黑名单: 退出后的token
if (tokenIndex !== -1) return ctx.tokenExpires('token已经失效');
// 解析token并存储到ctx的上面, ctx.state 本次请求的共享数据
ctx.state.user = getUser(token);
}
}
await next();
};
// app.js全局引入
const { responseHandler, checkLogin } = require('./middlewares');
app.use(checkLogin);
2.5、用户详情
router.prefix('/user')
.get('/info',getInfo)
exports.getInfo = async (ctx) => {
const user = ctx.state.user;
if (!user) return ctx.faild('用户信息获取失败!');
const { id } = user;
const res = await findUserById(id);
const dbUser = res[0];
if (!dbUser) return ctx.faild('用户信息不存在,或者已经被删除');
ctx.success({
info: '获取成功!',
roles: [{ name: dbUser.role_name }],
});
};
exports.findUserById = id => query('select * from user where id = ?',[id]);
2.6、退出
router.prefix('/user')
.post('/logout',logout)
// 退出后的token 在app.js全局添加
app.context.blackTokenList = [];
exports.logout = async (ctx) => {
ctx.blackTokenList.push(ctx.headers.token);
return ctx.tokenExpires('退出成功');
};