个人网站开发记录(三)一系统后端nodejs+express+mysql

前言

为什么后端选择nodejs呢,简单来说就是因为这样比较简单(确信),不过实际上主要是因为idea我的学生认证搞起来很麻烦,用同济的邮箱疑似不行,还得去找其他学校的同学的邮箱......总之总之最后的技术选型就是nodejs,然后框架用的是express.github代码链接:GitHub - RidenShogunei/personal-blog-nodejs-backend: 一个nodejs写的后端,正在更新

正文

简单来说,在搭建后端时候主要遇到的问题就三个,一个是如何分模块写,一个是解决跨域问题,一个是真正的写接口,当然数据库也遇到了问题()

项目结构

很简单的项目结构,实际上一共就四个接口

├─ app.js

├─ modle

│  ├─ diary.js

│  └─ personal.js

├─ package-lock.json

├─ package.json

└─ README.md

分模块

这里实际上就是要学会module.exports,然后在app.js也就是主文件里引入即可,分模块写的话就不用把代码全部堆在主文件里,修改接口啥的也很方便,就像下面这样:

module.exports = function (conn) {
  const express = require('express');
  const router = express.Router();
  const moment = require('moment-timezone');
  router.post('/submit', (req, res) => {
    console.log("Data received!");
    console.log(req.body);
    let data = req.body.data;
    let time = req.body.time;
    let sqlStr = `INSERT INTO diary (data, time) VALUES('${data}', '${time}')`;

    conn.query(sqlStr, (err) => {
      if (err) {
        console.error("插入失败:", err);
        res.send("插入失败");
      } else {
        console.log("插入成功");
        res.send('插入成功');
      }
    });
  });

  router.post('/search', (req, res) => {
    console.log("search received!");
    console.log(req.body); //这里会打印你发送的数据
    let data = req.body.data;
    let time = req.body.time;
    console.log("收到的数据", data, time);
    let sqlStr; // 在这里定义sqlStr
    if (data === "" && time === "") {
      sqlStr = `SELECT * FROM diary`;
    } else if (data === "") {
      time = moment(time).tz('Asia/Shanghai').format();
      time = time.substring(0, 10); // "2024-03-11"
      console.log("修改的数据", data, time);
      sqlStr = `SELECT * FROM diary where time = '${time}'`; // 使用单个等号进行比较
    } else if (time === "") {
      sqlStr = `SELECT * FROM diary where data LIKE '%${data}%'`; // 使用单个等号进行比较
    } else {
      time = moment(time).tz('Asia/Shanghai').format();
      time = time.substring(0, 10); // "2024-03-11"
      console.log("修改的数据", data, time);
      sqlStr = `SELECT * FROM diary WHERE time = '${time}' AND data LIKE '%${data}%'`;
    }
    conn.query(sqlStr, (err, results) => {
      if (err) {
        console.error("查询失败:", err);
        res.send("查询失败");
      } else {
        console.log("查询成功");
        let detile = results.map(row => {
          return {
            time: row.time,
            data: row.data
          }
        });
        console.log(detile);
        res.send(detile);
      }
    });
  });
  return router;
}

解决跨域问题

实际上就是简单的设置cors就行,就像这样:

app.use(cors());

但是这样以后有可能有个隐患,就是以后要用到cookie的话要是跨域的话就会比较麻烦,所以其实最好是用nginx将前后端代理在同一个端口,这样就完全没有跨域问题.

真正的写接口

到这一步了其实挺简单的,实际上在一系统的后端里我甚至没有做啥防注入之类的操作,还是比较危险而且简陋的.....,就像这样:

module.exports = function (conn) {
    const express = require('express');
    const router = express.Router();
    const moment = require('moment-timezone');

    router.post('/submit', (req, res) => {
        console.log("Data received!");
        console.log(req.body);
        let title = req.body.mytitle; // 新增
        let content = req.body.data;
        let time = req.body.time;
        let show = req.body.showornot;
        let sqlStr = `INSERT INTO personal (title, content, time,showornot) VALUES('${title}', '${content}', '${time}',${show})`; // 修改表名和字段名
        conn.query(sqlStr, (err) => {
            if (err) {
                console.error("插入失败:", err);
                res.send("插入失败");
            } else {
                console.log("插入成功");
                res.send('插入成功');
            }
        });
    });

    router.post('/get', (req, res) => {
        console.log("get received!");
        console.log(req.body);
        let title = req.body.title; // 新增
        let content = req.body.content;
        let time = req.body.time;
        let show=req.body.showornot;
        let sqlStr; // 在这里定义sqlStr
        if(show===""){
        sqlStr = `SELECT * FROM personal`;}
    else{
        sqlStr = `SELECT * FROM personal where showornot="1"`;}
        /*if (title === "" && content === "" && time === "") { // 新增title的判断
            sqlStr = `SELECT * FROM personal`;
        } else if (content === "" && time === "") {
            sqlStr = `SELECT * FROM personal where title LIKE '%${title}%'`;
        } else if (title === "" && time === "") {
            sqlStr = `SELECT * FROM personal where content LIKE '%${content}%'`;
        } else if (title === "" && content === "") {
            time = moment(time).tz('Asia/Shanghai').format();
            time = time.substring(0, 10); // "2024-03-11"
            sqlStr = `SELECT * FROM personal where time = '${time}'`;
        } else if (time === "") {
            sqlStr = `SELECT * FROM personal WHERE title LIKE '%${title}%' AND content LIKE '%${content}%'`;
        } else if (content === "") {
            time = moment(time).tz('Asia/Shanghai').format();
            time = time.substring(0, 10); // "2024-03-11"
            sqlStr = `SELECT * FROM personal WHERE time = '${time}' AND title LIKE '%${title}%'`;
        } else if (title === "") {
            time = moment(time).tz('Asia/Shanghai').format();
            time = time.substring(0, 10); // "2024-03-11"
            sqlStr = `SELECT * FROM personal WHERE time = '${time}' AND content LIKE '%${content}%'`;
        } else {
            time = moment(time).tz('Asia/Shanghai').format();
            time = time.substring(0, 10); // "2024-03-11"
            sqlStr = `SELECT * FROM personal WHERE time = '${time}' AND title LIKE '%${title}%' AND content LIKE '%${content}%'`;
        }*/

        conn.query(sqlStr, (err, results) => {
            if (err) {
                console.error("查询失败:", err);
                res.send("查询失败");
            } else {
                console.log("查询成功");
                let detail = results.map(row => {
                    return {
                        title: row.title, // 新增
                        content: row.content,
                        time: row.time
                    }
                });
                console.log(detail);
                res.send(detail);
            }
        });
    });
    return router;
}

实际上这里应该要进行如下的操作之一会比较好:

1.预处理语句 (Prepared Statements),或者叫参数化的过程 (Parameterized Queries)。比如,使用问号 ? 作为占位符,然后通过传入参数的方式插入值。这样就能保证用户的输入不会改变 SQL 的逻辑,避免 SQL 注入漏洞。

下面是使用参数化查询的例子:

let sqlStr = `INSERT INTO personal (title, content, time,showornot) VALUES(?, ?, ?, ?)`;
conn.query(sqlStr, [title, content, time, show], (err) => {
    //...
});

2.数据库API的转义函数。像是mysql库提供的mysql.escape()可以做这个工作。

数据库的坑

讲起来这才是我写这个后端遇到的最大的坑,足足烦了我一晚上加一上午,我是在阿里云服务器先下载好了mysql并且确信是跑在了3306端口,也确信服务本身的启动和监听都是正常的,同时也打开了防火墙的3306端口,然后我就开始尝试用本地的navicat来连接服务器的数据库,当然这是连接不上  的,因为实际上还需要设置sql账号的访问范围,于是我设置了root的访问范围是%,结果当然是访问不上,然后我又开了个新的账号,也设置其范围为%,再次访问,居然还是不行!!!!这下我实在是万策尽了,实在是想不到为什么这还是链接不上,之后在朋友和我的共同努力下,我们发现,处于某种原因,阿里云的防火墙对于3306端口的开启在刷新之后就会变成关闭!!!!!于是我们重新的设置了防火墙规则,这些终于连接上了!!之后的建表啥的就是小菜一碟了.

结语

简单来说,踩得最大的坑是数据库的链接问题.....

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值