选题及构思
学的硬件,毕业设计如果做硬件实物又是一笔钱,最后选择了一个软件的题目,正好用来练手。
前后端基于JS的博客系统,用于完成毕业设计,初想使用koa作为后端,vue作为前端来完成,以后可能会改变
目录结构
第一部分先完成后端的koa路由、token授权、mysql操作类。
│ index.js
│ package-lock.json
│
├─config
│ config.js
│ sql.js
│ token.js
│
└─router
  article.js
以上为项目基础目录:index.js是入口文件;config为配置目录,其中的config.js主要是参数配置文件,sql.js为mysql的操作类,token.js生成token的方法、以及注册账号功能;router目录下的所有文件将自动加载为koa的路由,加载规则为:"/文件名/内置路由名",例如此例路由为:“/article/”。
程序代码
index.js文件:
const Koa = require("koa");//web服务库
const Router = require("koa-router");//koa路由
const Koapost = require("koa-body");//基于koa的post接收库
const jwt = require("jwt-simple");//json web token库
const config = require("./config/config");//配置文件
const jstSecret = config.jstSecret;//token密钥
const app = new Koa();
const router = new Router();
app.use(Koapost());//获得post信息
let token = require(__dirname + '/config/token.js');//加载登陆注册中间件
router.use('/user', token.routes(), token.allowedMethods());
app.use(router.routes());//挂载登陆注册中间件
app.use(async (ctx, next) => {
if (ctx.request.header.authorization !== undefined) {
let user = jwt.decode(ctx.request.header.authorization, jstSecret);
if(Date.now() > user.exp){
ctx.response.status = 403;
ctx.response.body = {
msg: "token已过期,请重新授权",
"status": "-1"
}
}else{
await next();
}
} else {
ctx.response.status = 401;
ctx.response.body = {
msg: "非授权操作!",
"status": "-1"
}
}
});
const fs = require("fs");
const urls = fs.readdirSync(__dirname + '/router');//获得所有子路由文件
urls.forEach(element => {//循环注册所有子路由
let url = require(__dirname + '/router/' + element);
router.use('/' + element.replace('.js', ''), url.routes(), url.allowedMethods());
});
app.use(router.routes());//把子路由挂载到koa之上
app.listen(3000);
config.js文件:
module.exports = {
jstSecret: 'No permission',//jwt密钥
tokenExpiresTime: 1000 * 60 * 60 * 24 * 7,//token过期时间
mysql:{
host: "No permission",//数据库地址
port: "No permission",//端口
user: "No permission",//用户名
password: "No permission",//密码
database: "No permission"//数据库名
}
}
sql.js文件:
const mysql = require("mysql");//mysql操作库
const config = require("./config");//配置文件
const _db = Symbol("db");
class Sql {
constructor() {
this[_db] = mysql.createPool({
host: config.mysql.host,
port: config.mysql.port,
user: config.mysql.user,
password: config.mysql.password,
database: config.mysql.database
});
}
query(sql, value) {
return new Promise((resove, reject) => {
this[_db].getConnection((err, connection) => {
if(err){
reject(err);
}else{
connection.query(sql, value, (err, rows)=>{
if(err){
reject(err);
}else{
resove(rows);
}
})
connection.release();
}
})
})
}
}
module.exports = Sql;
token.js文件:
const Router = require("koa-router");//koa路由
const jwt = require("jwt-simple");//json web token库
const utility = require("utility");//sh1、md5加密库
const sql = require("./sql");//mysql封装类
const config = require("./config");//配置文件
const sqlQuery = new sql();
const token = new Router();
const tokenExpiresTime = config.tokenExpiresTime;//token超时时间
const jstSecret = config.jstSecret;//token密钥
token.post('/login', async ctx => {
if(ctx.request.body.user === undefined || ctx.request.body.password === undefined){
//检查是否存在post数据
ctx.response.status = 400;
ctx.response.body = {
"msg": "登陆参数不正确!",
"status": "-1"
}
}else{
//验证账号密码的正确性
let post_user = ctx.request.body.user;
let post_password = utility.md5(utility.md5(ctx.request.body.password));
let con = await sqlQuery.query("SELECT * FROM user WHERE name=? AND password=?", [post_user, post_password]);
if(con.length === 1){
const payload = {
'sub': post_user,
'exp': Date.now() + tokenExpiresTime
};
const token = jwt.encode(payload, jstSecret);
ctx.response.status = 200;
ctx.response.body = {
"msg": "授权成功!",
"user": post_user,
"token": token,
"status": "0"
};
}else{
ctx.response.status = 200;
ctx.response.body = {
"msg": "账号或者密码错误!",
"status": "-1"
}
}
}
})
module.exports = token;
article.js文件:
const Router = require("koa-router");
const article = new Router();
article.get('/', async (ctx, next) => {
ctx.response.status = 200;
ctx.response.body = "article";
await next();
});
article.get('/list', async (ctx, next) => {
ctx.response.status = 200;
ctx.response.body = "article/list";
await next();
});
module.exports = article;
程序执行流程
- 运行index.js文件,先把Koapost()方法挂载到koa中间件上,它的作用是接收post过来的参数,可以用ctx.request.body来获得
- 加载config/token.js路由到koa中间件,这个中间站在第二个位置,它的作用是token授权;
- 接着就是整体路由监控,排除授权token接口外所有接口都要经过此接口,token验证失败时就会报错,验证成功才能进行其它操作。
- 然后循环读取router文件夹下的所有文件,把其中定义的路由全部加载到koa中间件下
整体框架大致如此,之后的文章将不会在贴代码,而只记录实现过程,代码将会托管在github中
0 评论