基于Node.js使用express搭建的简单服务器

入口文件app.js

// 导入express
const express = require('express');
// 导入user路由接口
const userRouter = require('./routers/user.js');
// 导入staticResource(静态资源)接口
const staticResourceRouter = require('./routers/staticResource.js');
// 导入path模块
const path = require('path');
// 处理中间件,在进行post请求时可以拿到客户端发送过来的参数,负责解析表单提交
const bodyParser = require('body-parser');
// 处理cookie和session
const cookieSession = require('cookie-session');
//创建express实例
const app = express();

// 处理静态资源
app.use(express.static(path.join(__dirname, 'public'), { extensions: ['html', 'htm','css','js'] }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());

// 处理ajax向后台请求数据产生的跨域问题
app.all('*', function (req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  // res.header("Access-Control-Allow-Headers", "Content-Type, X-Requested-With");
  // res.header("Access-Control-Allow-Headers", "Content-Type, application/json");
  res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  if (req.method.toLowerCase() == 'options') {
    res.send(200);
  } else {
    next();
  }
})

// 将中间件函数安装在指定路径上
app.use('/user', userRouter);
app.use('/staticRes', staticResourceRouter);

// 设置根路径,也就是输入默认端口时显示的路径
app.get('/', function (req, res, next) {
  // 该处表示输入根目录(默认端口时),将重定向(跳转)到/yukino路径所在的页面
  res.redirect('/yukino');
});
app.get('/yukino', function (req, res, next) {
  res.send('hello word')
})

// 监听3000端口
app.listen(3000, "0.0.0.0");
console.log('Example app listening on port 3000!')

用户路由user.js

// 用户路由部分
// 导入express模块
const express = require('express');
// 导入数据库接口(从mysql里面导出的dbQuery函数查询接口)
const { dbQuery } = require('../mysql.js');
// 获取路由对象
const router = express.Router();
// 导入token
const tokenMsg = require('../token.js');

// 回调函数,将验证后的用户注册数据插入数据库
const writeToMysql = function (req, res, formData) {
  let sqlRegister = `INSERT INTO username (name, tel, email, password) VALUES ('${formData.name}', '${formData.tel}', '${formData.email}, '${formData.pw1}'')`;
  dbQuery(sqlRegister, function (results, fields, error) {
    if (results) {
      res.send({
        state: 200,
        des: "注册成功"
      })
    };
    if (error) {
      res.send({
        state: 500,
        des: "注册失败",
        error: error
      })
    }
  })
}

// 用户注册部分
router.post('/register', function (req, res, next) {
  console.log('有人要注册');
  let formData = req.body;
  for (key in formData) {
    if (formData[key] === '') {
      res.send({
        state: 400,
        des: "每一项的值不能为空"
      })
      return
    }
  };
  if (formData.pw1 !== formData.pw2) {
    res.send({
      state: 400,
      des: "两次密码不一样"
    })
    return
  };

  let userName = formData.name;
  let sqlName = 'SELECT name FROM username';
  dbQuery(sqlName, function (results, fields, error) {
    let getResults = JSON.parse(JSON.stringify(results));
    for (let i = 0; i <= getResults.length - 1; i++) {
      if (userName === getResults[i].name) {
        res.send({
          state: 400,
          des: "您输入的用户名错误"
        })
        return
      }
    }
    // 调用回调函数,将数据写入数据库
    return writeToMysql(req, res, formData);
  })
})

// 用户登录部分,登录以后将会获的一个token数据
router.post('/login', function (req, res, next) {
  console.log('有人要登录');
  let formData = req.body;

  if (formData.name === '' || formData.pw1 === '') {
    res.send({
      state: 400,
      des: "账户或者密码不能为空"
    })
    return
  }
  let sqlLogin = `SELECT * FROM username WHERE name='${formData.name}' AND password='${formData.pw1}'`;
  dbQuery(sqlLogin, function (results, fields, error) {
    //console.log(res.json(resluts));
    if (results.length > 0) {
      // 获取通过该用户的用户名生成的token
      let userToken = tokenMsg.tokenObj.createToken(formData.name, 60 * 30);
      //req.session.uid = results[0].id;
      console.log('登录成功');
      // 将结果和用户token返回给前端
      res.json({
        state: 200,
        results: results,
        token: userToken
      })   
    } else {
      res.send({
        state: 400,
        des: "账户或者密码错误"
      })
    }
  })
})

// 已登录用户查询信息,验证token成功以后,将用户数据返回给前端
router.post('/queryUserData', function (req, res, next) {
  // 获取前端传来的token
  let token = req.body.token;
  // 验证token
  tokenMsg.tokenObj.checkToken(token, function () {
    // 获取用户的用户名
    let name = req.body.name;
    let sqlToken = `SELECT * REOM username WHERE name='${name}'`;
    dbQuery(sqlToken, function (resluts, fields, error) {
      if (error) {
        console.log('出错了:' + error.message);
        res.send({
          state: 400,
          des: '出错了:' + error.message
        })
      } else {
        if (results.length === 0) {
          console.log('该用户无其他任何数据');
          res.send({
            state: 404,
            des: "该用户无其他任何数据"
          })
        } else {
          console.log('验证token及数据库查询成功,已返回数据给前端');
          res.json({
            state: 200,
            des: results 
          })
        }
      }
    })
  })
})

// 导出user路由
module.exports = router;

静态资源路由staticResource.js

// 导入数据库查询接口
const { dbQuery } = require('../mysql.js');
// 导入express模块
const express = require('express');
// 获取路由对象
const router = express.Router();

// 访问数据库并获取数据
router.get('/resource', function (req, res, next) {
  let value = req.query.val;
  let sql = `SELECT * FROM ${value}`;
  dbQuery(sql, function (results, fields, error) {
    if (error) {
      res.send({
        state: 400,
        des: error.message
      })
    } else {
      res.json({
        state: 200,
        des: results
      })
    }
  })
})

// 导出路由
module.exports = router;

连接数据库文件mysql.js

// mysql 数据库与后台(express框架)的链接
const mysql = require('mysql');
// 默认配置,输入参数链接数据库
function dbConn() {
  let connection = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'xxxxx',
    // 前一个是与数据库的连接名,后一个是数据库的名字
    yukino: 'yukino'
  })
  return connection;
}

function dbQuery(sql, callback) {
  // 调用回调函数链接数据库
  let conn = dbConn();
  // 打开数据库
  conn.connect();
  // 传入mysql查询语句,返回对应的结果
  conn.query(sql, function (results, fields, error) {
    if (error) {
      throw error
    } else {
      callback(results, fields)
    }
  })
  //关闭数据库
  conn.end();
}

// 导出数据库接口
module.exports = {
  dbConn: dbConn,
  dbQuery: dbQuery
}

请求数据验证信息token.js

// 我们需要每次都知道当前请求的人是谁,但是又不想每次都让他提交用户名和密码,这时就需要有一个等同于用户名密码也能够标识用户身份的东西,即---token.
// 1. 客户端使用用户名和密码请求登录
// 2. 服务端收到请求,验证登录是否成功
// 3. 验证成功后,服务端会返回一个Token给客户端,反之,返回身份验证失败的信息
// 4. 客户端收到Token后把Token用一种方式存储起来,如( cookie / localstorage / sessionstorage / 其他 )
// 5. 客户端每次发起请求时都会将Token发给服务端
// 6. 服务端收到请求后,验证Token的合法性,合法就返回客户端所需数据,反之,返回验证失败的信息

// 导入token模块
const jwt = require('jsonwebtoken');
const tokenObj = {
  // 生成token部分
  createToken: function (cont, time) {
    let content = {
      // 要生成token的主题信息(这里包含用户的一些相关信息,content需要为一个对象,否则有可能报错)
      msg: cont
    }
    // 这是加密的key (密钥或私钥)
    let secretOrPrivateKey = "yukinoshitayukino";
    // 生成token
    let token = jwt.sign(content, secretOrPrivateKey, function (error, decode) {
      // 设置token的过期时间,以秒作为单位
      expiresIn: time
    })
    // 将token作为返回值传出去
    return token;
  },

  // 验证token部分
  checkToken: function (token, fn) {
    //console.log(fn);
    // 这是加密的key (密钥或私钥),这里可以将上面的这个变量写为tokenObj里面的全局,这样就可以直接调用了
    let secretOrPrivateKey = "yukinoshitayukino";
    // 验证token
    jwt.verify(token, secretOrPrivateKey, function (error, decode) {
      // 当token过期,或这是一个伪造的token,或是无效的token时会触发此逻辑
      if (error) {
        throw error
      } else {
        console.log('验证成功' + decode.msg);
        fn();
      }
    })
  }
}

// 导出token
module.exports.tokenObj = tokenObj;
讨论数量: 0

慎思笃行